diff --git a/.gitignore b/.gitignore
index a47e7fe79..55e8841b8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,8 +39,5 @@ envs.env
# database
mariadb
-# data test
-library
-
# config test
romm
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a0a899c85..62cecd182 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,20 @@
+# v1.8 (_25-04-2023_)
+
+## Added
+ - Home screen.
+ - Config option to associate custom system folders to platforms (Complete scan needed). Check [config.yml](docker/config.example.yml) example. Solves [#152](https://github.com/zurdi15/romm/issues/152).
+ - Sega Saturn and Master System support added. Check [platforms support](https://github.com/zurdi15/romm#platforms-support). Solves [#194](https://github.com/zurdi15/romm/issues/194).
+ - Progress bar when games are being downloaded.
+## Changed
+ - Routes to different RomM sections and games changed now allow share direct links to platforms and games.
+ - RomM now can scan subdirectories in a multi-part game. Solves [#179](https://github.com/zurdi15/romm/issues/179).
+ - Settings and Scan sections are now in the main drawer menu.
+ - Some UI changes.
+## Fixed
+ - Code base stability and speed improved.
+
+
+
# v1.7.1 (_15-04-2023_)
## Added
diff --git a/README.md b/README.md
index 63a9e3716..1fda9e5c9 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
@@ -44,11 +44,11 @@ Available as a docker [image](https://hub.docker.com/r/zurdi15/romm) (amd64/arm6
## 🖥 Desktop
-
Video preview https://user-images.githubusercontent.com/34356590/227992371-33056130-c067-49c1-ae32-b3ba78db6798.mp4
+
Video preview https://user-images.githubusercontent.com/34356590/227992371-33056130-c067-49c1-ae32-b3ba78db6798.mp4
## 📱 Mobile
-
Video preview https://user-images.githubusercontent.com/34356590/228007442-0a9cbf6b-4b62-4c1a-aad8-48b13e6337e8.mp4
+
Video preview https://user-images.githubusercontent.com/34356590/228007442-0a9cbf6b-4b62-4c1a-aad8-48b13e6337e8.mp4
# Installation
@@ -129,75 +129,78 @@ This will change over the time, adding games metadata for more platforms. Make s
Platforms support list
-
-
-| slug | name | games metadata |
-|---------------|-------------------------------------| :----: |
-| 3ds | Nintendo 3DS | ✅ |
-| amiga | Amiga | ✅ |
-| arcade | Arcade | ✅ |
-| atari | atari | ❌ |
-| coleco | coleco | ❌ |
-| c64 | Commodore C64/128/MAX | ✅ |
-| cpc | cpc | ❌ |
-| cps1 | cps1 | ❌ |
-| cps2 | cps2 | ❌ |
-| cps3 | cps3 | ❌ |
-| daphne | daphne | ❌ |
-| dc | Dreamcast | ✅ |
-| dos | DOS | ✅ |
-| fairchild | fairchild | ❌ |
-| fba2012 | fba2012 | ❌ |
-| fbneo | fbneo | ❌ |
-| fds | Family Computer Disk System | ✅ |
-| gb | Game Boy | ✅ |
-| gba | Game Boy Advance | ✅ |
-| gbc | Game Boy Color | ✅ |
-| gg | gg | ❌ |
-| gw | gw | ❌ |
-| intellivision | Intellivision | ✅ |
-| jaguar | Atari Jaguar | ✅ |
-| lynx | Atari Lynx | ✅ |
-| md | md | ❌ |
-| megaduck | megaduck | ❌ |
-| ms | ms | ❌ |
-| msx | MSX | ✅ |
-| n64 | Nintendo 64 | ✅ |
-| nds | Nintendo DS | ✅ |
-| neocd | neocd | ❌ |
-| neogeo | neogeo | ❌ |
-| nes | Nintendo Entertainment System | ✅ |
-| ngc | Nintendo GameCube | ✅ |
-| ngp | ngp | ❌ |
-| odyssey | odyssey | ❌ |
-| pce | pce | ❌ |
-| pcecd | pcecd | ❌ |
-| pico | pico | ❌ |
-| poke | poke | ❌ |
-| ps | PlayStation | ✅ |
-| ps2 | PlayStation 2 | ✅ |
-| ps3 | PlayStation 3 | ✅ |
-| ps4 | ps4 | ❌ |
-| psp | PlayStation Portable | ✅ |
-| psvita | PlayStation Vita | ✅ |
-| scummvm | scummvm | ❌ |
-| segacd | Sega CD | ✅ |
-| segasgone | segasgone | ❌ |
-| sgb | sgb | ❌ |
-| sgfx | sgfx | ❌ |
-| snes | Super Nintendo Entertainment System | ✅ |
-| supervision | supervision | ❌ |
-| switch | Nintendo Switch | ✅ |
-| wii | Wii | ✅ |
-| win | PC (Microsoft Windows) | ✅ |
-| wiiu | Wii U | ✅ |
-| wonderswan | WonderSwan | ✅ |
-| wonderswan-color| WonderSwan Color | ✅ |
-| xbox | Xbox | ✅ |
-| xbox360 | Xbox 360 | ✅ |
-| xboxone | Xbox One | ✅ |
-
-
+
+
+| slug | name | games metadata |
+|--------------- |-------------------------------------| :----: |
+| 3ds | Nintendo 3DS | ✅ |
+| amiga | Amiga | ✅ |
+| arcade | Arcade | ✅ |
+| atari | atari | ❌ |
+| coleco | coleco | ❌ |
+| c64 | Commodore C64/128/MAX | ✅ |
+| cpc | cpc | ❌ |
+| cps1 | cps1 | ❌ |
+| cps2 | cps2 | ❌ |
+| cps3 | cps3 | ❌ |
+| daphne | daphne | ❌ |
+| dc | Dreamcast | ✅ |
+| dos | DOS | ✅ |
+| fairchild | fairchild | ❌ |
+| fba2012 | fba2012 | ❌ |
+| fbneo | fbneo | ❌ |
+| fds | Family Computer Disk System | ✅ |
+| gb | Game Boy | ✅ |
+| gba | Game Boy Advance | ✅ |
+| gbc | Game Boy Color | ✅ |
+| genesis-slash-megadrive | Sega Mega Drive/Genesis | ✅ |
+| gg | gg | ❌ |
+| gw | gw | ❌ |
+| intellivision | Intellivision | ✅ |
+| jaguar | Atari Jaguar | ✅ |
+| lynx | Atari Lynx | ✅ |
+| md | md | ❌ |
+| megaduck | megaduck | ❌ |
+| ms | ms | ❌ |
+| msx | MSX | ✅ |
+| n64 | Nintendo 64 | ✅ |
+| nds | Nintendo DS | ✅ |
+| neocd | neocd | ❌ |
+| neogeo | neogeo | ❌ |
+| nes | Nintendo Entertainment System | ✅ |
+| ngc | Nintendo GameCube | ✅ |
+| ngp | ngp | ❌ |
+| odyssey | odyssey | ❌ |
+| pce | pce | ❌ |
+| pcecd | pcecd | ❌ |
+| pico | pico | ❌ |
+| poke | poke | ❌ |
+| ps | PlayStation | ✅ |
+| ps2 | PlayStation 2 | ✅ |
+| ps3 | PlayStation 3 | ✅ |
+| ps4 | ps4 | ❌ |
+| psp | PlayStation Portable | ✅ |
+| psvita | PlayStation Vita | ✅ |
+| saturn | Sega Saturn | ✅ |
+| scummvm | scummvm | ❌ |
+| segacd | Sega CD | ✅ |
+| segasgone | segasgone | ❌ |
+| sms | Sega Master System/Mark III | ✅ |
+| sgb | sgb | ❌ |
+| sgfx | sgfx | ❌ |
+| snes | Super Nintendo Entertainment System | ✅ |
+| supervision | supervision | ❌ |
+| switch | Nintendo Switch | ✅ |
+| wii | Wii | ✅ |
+| win | PC (Microsoft Windows) | ✅ |
+| wiiu | Wii U | ✅ |
+| wonderswan | WonderSwan | ✅ |
+| wonderswan-color | WonderSwan Color | ✅ |
+| xbox | Xbox | ✅ |
+| xbox360 | Xbox 360 | ✅ |
+| xboxone | Xbox One | ✅ |
+
+
diff --git a/backend/src/alembic/env.py b/backend/src/alembic/env.py
index 933a84264..713a6a4d0 100644
--- a/backend/src/alembic/env.py
+++ b/backend/src/alembic/env.py
@@ -4,7 +4,8 @@
from logging.config import fileConfig
from sqlalchemy import create_engine
-from config.config_loader import get_db_engine
+from config.config_loader import ConfigLoader
+cl = ConfigLoader()
from alembic import context
@@ -45,8 +46,9 @@ def run_migrations_offline() -> None:
"""
context.configure(
- url=get_db_engine(),
+ url=cl.get_db_engine(),
target_metadata=target_metadata,
+ render_as_batch=True,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
@@ -63,11 +65,13 @@ def run_migrations_online() -> None:
"""
- engine = create_engine(get_db_engine())
+ engine = create_engine(cl.get_db_engine())
with engine.connect() as connection:
context.configure(
- connection=connection, target_metadata=target_metadata
+ connection=connection,
+ target_metadata=target_metadata,
+ render_as_batch=True
)
with context.begin_transaction():
diff --git a/backend/src/alembic/versions/1.6.2_.py b/backend/src/alembic/versions/1.6.2_.py
index 399921a33..423607f8a 100644
--- a/backend/src/alembic/versions/1.6.2_.py
+++ b/backend/src/alembic/versions/1.6.2_.py
@@ -1,4 +1,4 @@
-"""init
+"""init to 1.6.2
Revision ID: 1.6.2
Revises:
@@ -21,35 +21,35 @@ def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
try:
op.create_table('platforms',
- sa.Column('igdb_id', sa.String(length=10), nullable=True),
- sa.Column('sgdb_id', sa.String(length=10), nullable=True),
- sa.Column('slug', sa.String(length=50), nullable=False),
- sa.Column('name', sa.String(length=400), nullable=True),
- sa.Column('logo_path', sa.String(length=1000), nullable=True),
- sa.Column('n_roms', sa.Integer(), nullable=True),
- sa.PrimaryKeyConstraint('slug')
+ sa.Column('igdb_id', sa.String(length=10), nullable=True),
+ sa.Column('sgdb_id', sa.String(length=10), nullable=True),
+ sa.Column('slug', sa.String(length=50), nullable=False),
+ sa.Column('name', sa.String(length=400), nullable=True),
+ sa.Column('logo_path', sa.String(length=1000), nullable=True),
+ sa.Column('n_roms', sa.Integer(), nullable=True),
+ sa.PrimaryKeyConstraint('slug')
)
op.create_table('roms',
- sa.Column('r_igdb_id', sa.String(length=10), nullable=True),
- sa.Column('p_igdb_id', sa.String(length=10), nullable=True),
- sa.Column('r_sgdb_id', sa.String(length=10), nullable=True),
- sa.Column('p_sgdb_id', sa.String(length=10), nullable=True),
- sa.Column('p_slug', sa.String(length=50), nullable=False),
- sa.Column('file_name', sa.String(length=450), nullable=False),
- sa.Column('file_name_no_tags', sa.String(length=450), nullable=True),
- sa.Column('file_extension', sa.String(length=10), nullable=True),
- sa.Column('file_path', sa.String(length=1000), nullable=True),
- sa.Column('file_size', sa.Float(), nullable=True),
- sa.Column('name', sa.String(length=350), nullable=True),
- sa.Column('r_slug', sa.String(length=100), nullable=True),
- sa.Column('summary', sa.Text(), nullable=True),
- sa.Column('path_cover_s', sa.Text(), nullable=True),
- sa.Column('path_cover_l', sa.Text(), nullable=True),
- sa.Column('has_cover', sa.Boolean(), nullable=True),
- sa.Column('region', sa.String(length=20), nullable=True),
- sa.Column('revision', sa.String(length=20), nullable=True),
- sa.Column('tags', sa.JSON(), nullable=True),
- sa.PrimaryKeyConstraint('p_slug', 'file_name')
+ sa.Column('r_igdb_id', sa.String(length=10), nullable=True),
+ sa.Column('p_igdb_id', sa.String(length=10), nullable=True),
+ sa.Column('r_sgdb_id', sa.String(length=10), nullable=True),
+ sa.Column('p_sgdb_id', sa.String(length=10), nullable=True),
+ sa.Column('p_slug', sa.String(length=50), nullable=False),
+ sa.Column('file_name', sa.String(length=450), nullable=False),
+ sa.Column('file_name_no_tags', sa.String(length=450), nullable=True),
+ sa.Column('file_extension', sa.String(length=10), nullable=True),
+ sa.Column('file_path', sa.String(length=1000), nullable=True),
+ sa.Column('file_size', sa.Float(), nullable=True),
+ sa.Column('name', sa.String(length=350), nullable=True),
+ sa.Column('r_slug', sa.String(length=100), nullable=True),
+ sa.Column('summary', sa.Text(), nullable=True),
+ sa.Column('path_cover_s', sa.Text(), nullable=True),
+ sa.Column('path_cover_l', sa.Text(), nullable=True),
+ sa.Column('has_cover', sa.Boolean(), nullable=True),
+ sa.Column('region', sa.String(length=20), nullable=True),
+ sa.Column('revision', sa.String(length=20), nullable=True),
+ sa.Column('tags', sa.JSON(), nullable=True),
+ sa.PrimaryKeyConstraint('p_slug', 'file_name')
)
except OperationalError:
pass
diff --git a/backend/src/alembic/versions/1.6.3_.py b/backend/src/alembic/versions/1.6.3_.py
index bdf5255be..69d1f91f7 100644
--- a/backend/src/alembic/versions/1.6.3_.py
+++ b/backend/src/alembic/versions/1.6.3_.py
@@ -1,4 +1,4 @@
-"""add multifile games
+"""update to 1.6.3
Revision ID: 1.6.3
Revises: 1.6.2
@@ -18,13 +18,15 @@
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
- op.add_column('roms', sa.Column('multi', sa.Boolean(), nullable=True))
- op.add_column('roms', sa.Column('files', sa.JSON(), nullable=True))
+ with op.batch_alter_table("roms") as batch_op:
+ batch_op.add_column(sa.Column('multi', sa.Boolean(), nullable=True))
+ batch_op.add_column(sa.Column('files', sa.JSON(), nullable=True))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
- op.drop_column('roms', 'files')
- op.drop_column('roms', 'multi')
+ with op.batch_alter_table("roms") as batch_op:
+ batch_op.drop_column('files')
+ batch_op.drop_column('multi')
# ### end Alembic commands ###
diff --git a/backend/src/alembic/versions/1.7.1_.py b/backend/src/alembic/versions/1.7.1_.py
index b53666d11..015bace17 100644
--- a/backend/src/alembic/versions/1.7.1_.py
+++ b/backend/src/alembic/versions/1.7.1_.py
@@ -1,4 +1,4 @@
-"""empty message
+"""update to 1.7.1
Revision ID: 1.7.1
Revises: 1.6.3
@@ -18,11 +18,13 @@
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
- op.add_column('roms', sa.Column('file_size_units', sa.String(length=10), nullable=True))
+ with op.batch_alter_table("roms") as batch_op:
+ batch_op.add_column(sa.Column('file_size_units', sa.String(length=10), nullable=True))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
- op.drop_column('roms', 'file_size_units')
+ with op.batch_alter_table("roms") as batch_op:
+ batch_op.drop_column('file_size_units')
# ### end Alembic commands ###
diff --git a/backend/src/alembic/versions/1.8_.py b/backend/src/alembic/versions/1.8_.py
new file mode 100644
index 000000000..5f87b582f
--- /dev/null
+++ b/backend/src/alembic/versions/1.8_.py
@@ -0,0 +1,104 @@
+"""update to 1.8
+
+Revision ID: 1.8
+Revises: 1.7.1
+Create Date: 2023-04-17 12:03:19.163501
+
+"""
+import os
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects import sqlite
+
+
+# revision identifiers, used by Alembic.
+revision = '1.8'
+down_revision = '1.7.1'
+branch_labels = None
+depends_on = None
+
+
+def upgrade() -> None:
+ # ### commands auto generated by Alembic - please adjust! ###
+ with op.batch_alter_table("platforms") as batch_op:
+ batch_op.execute("ALTER TABLE platforms RENAME TO old_platforms")
+ op.create_table('platforms',
+ sa.Column('igdb_id', sa.String(length=10), nullable=True),
+ sa.Column('sgdb_id', sa.String(length=10), nullable=True),
+ sa.Column('slug', sa.String(length=50), nullable=False),
+ sa.Column('fs_slug', sa.String(length=50), nullable=False),
+ sa.Column('name', sa.String(length=400), nullable=True),
+ sa.Column('logo_path', sa.String(length=1000), nullable=True),
+ sa.Column('n_roms', sa.Integer(), nullable=True),
+ sa.PrimaryKeyConstraint('fs_slug')
+ )
+ batch_op.execute("INSERT INTO platforms(igdb_id, sgdb_id, slug, fs_slug, name, logo_path, n_roms) \
+ SELECT igdb_id, sgdb_id, slug, slug, name, logo_path, n_roms \
+ FROM old_platforms")
+ op.drop_table('old_platforms')
+
+
+ with op.batch_alter_table("roms") as batch_op:
+ batch_op.add_column(sa.Column('p_name', sa.String(length=150), nullable=True))
+ batch_op.add_column(sa.Column('url_cover', sa.Text(), nullable=True))
+ batch_op.alter_column('name', new_column_name='r_name', type_=sa.String(length=150), existing_type=sa.String(length=150))
+ batch_op.alter_column('p_slug', existing_type=sa.String(length=50), nullable=False)
+ batch_op.alter_column('file_name', existing_type=sa.String(length=450), nullable=False)
+ with op.batch_alter_table("roms") as batch_op:
+ batch_op.execute("ALTER TABLE roms RENAME TO old_roms")
+ op.create_table('roms',
+ sa.Column('id', sa.Integer(), autoincrement=True),
+ sa.Column('r_igdb_id', sa.String(length=10), nullable=True),
+ sa.Column('p_igdb_id', sa.String(length=10), nullable=True),
+ sa.Column('r_sgdb_id', sa.String(length=10), nullable=True),
+ sa.Column('p_sgdb_id', sa.String(length=10), nullable=True),
+ sa.Column('p_slug', sa.String(length=50), nullable=False),
+ sa.Column('p_name', sa.String(length=150), nullable=True),
+ sa.Column('file_name', sa.String(length=450), nullable=False),
+ sa.Column('file_name_no_tags', sa.String(length=450), nullable=False),
+ sa.Column('file_extension', sa.String(length=10), nullable=True),
+ sa.Column('file_path', sa.String(length=1000), nullable=True),
+ sa.Column('file_size', sa.Float(), nullable=True),
+ sa.Column('file_size_units', sa.String(length=10), nullable=True),
+ sa.Column('r_name', sa.String(length=350), nullable=True),
+ sa.Column('r_slug', sa.String(length=100), nullable=True),
+ sa.Column('summary', sa.Text(), nullable=True),
+ sa.Column('path_cover_s', sa.Text(), nullable=True),
+ sa.Column('path_cover_l', sa.Text(), nullable=True),
+ sa.Column('has_cover', sa.Boolean(), nullable=True),
+ sa.Column('region', sa.String(length=20), nullable=True),
+ sa.Column('revision', sa.String(length=20), nullable=True),
+ sa.Column('tags', sa.JSON(), nullable=True),
+ sa.Column('multi', sa.Boolean(), nullable=True),
+ sa.Column('files', sa.JSON(), nullable=True),
+ sa.Column('url_cover', sa.Text(), nullable=True),
+ sa.PrimaryKeyConstraint('id')
+ )
+ batch_op.execute("INSERT INTO roms(\
+ r_igdb_id, p_igdb_id, r_sgdb_id, p_sgdb_id, p_slug, p_name, \
+ file_name, file_name_no_tags, file_extension, file_path, file_size, \
+ file_size_units, r_name, r_slug, summary, path_cover_s, path_cover_l, has_cover, \
+ region, revision, tags, multi, files, url_cover) \
+ SELECT \
+ r_igdb_id, p_igdb_id, r_sgdb_id, p_sgdb_id, p_slug, p_name, \
+ file_name, file_name_no_tags, file_extension, file_path, file_size, \
+ file_size_units, r_name, r_slug, summary, path_cover_s, path_cover_l, has_cover, \
+ region, revision, tags, multi, files, url_cover \
+ FROM old_roms")
+ op.drop_table('old_roms')
+ # ### end Alembic commands ###
+
+
+def downgrade() -> None:
+ # ### commands auto generated by Alembic - please adjust! ###
+ with op.batch_alter_table("platforms") as batch_op:
+ batch_op.drop_column('fs_slug')
+ with op.batch_alter_table("roms") as batch_op:
+ batch_op.drop_constraint('PRIMARY', type_="primary")
+ batch_op.drop_column('id')
+ batch_op.drop_column('p_name')
+ batch_op.drop_column('url_cover')
+ batch_op.alter_column('r_name', new_column_name='name', type_=sa.String(length=150), existing_type=sa.String(length=150))
+ batch_op.alter_column('p_slug', existing_type=sa.String(length=50), nullable=False)
+ batch_op.alter_column('file_name', existing_type=sa.String(length=450), nullable=False)
+ # ### end Alembic commands ###
diff --git a/backend/src/config/config_loader.py b/backend/src/config/config_loader.py
index efc0be00d..5a991bc14 100644
--- a/backend/src/config/config_loader.py
+++ b/backend/src/config/config_loader.py
@@ -2,30 +2,36 @@
import sys
from urllib.parse import quote_plus
-from config import ROMM_DB_DRIVER, SUPPORTED_DB_DRIVERS, SQLITE_DB_BASE_PATH
+from config import ROMM_DB_DRIVER, SUPPORTED_DB_DRIVERS, SQLITE_DB_BASE_PATH, user_config
from logger.logger import log
-def get_db_engine():
- if ROMM_DB_DRIVER in SUPPORTED_DB_DRIVERS:
-
- if ROMM_DB_DRIVER == 'mariadb':
- DB_HOST: str = os.getenv('DB_HOST')
- try:
- DB_PORT: int = int(os.getenv('DB_PORT'))
- except TypeError:
- log.critical(f"DB_PORT variable not set properly")
- sys.exit(3)
- DB_USER: str = os.getenv('DB_USER')
- DB_PASSWD: str = os.getenv('DB_PASSWD')
- DB_NAME: str = os.getenv('DB_NAME', 'romm')
-
- return f"mariadb+mariadbconnector://{DB_USER}:%s@{DB_HOST}:{DB_PORT}/{DB_NAME}" % quote_plus(DB_PASSWD)
-
- elif ROMM_DB_DRIVER == 'sqlite':
- if not os.path.exists(SQLITE_DB_BASE_PATH): os.makedirs(SQLITE_DB_BASE_PATH)
- return f"sqlite:////{SQLITE_DB_BASE_PATH}/romm.db"
-
- else:
- log.critical(f"{ROMM_DB_DRIVER} database not supported")
- sys.exit(3)
+class ConfigLoader:
+
+ def __init__(self):
+ pass
+
+
+ def get_db_engine(self):
+ if ROMM_DB_DRIVER in SUPPORTED_DB_DRIVERS:
+
+ if ROMM_DB_DRIVER == 'mariadb':
+ DB_HOST: str = os.getenv('DB_HOST')
+ try:
+ DB_PORT: int = int(os.getenv('DB_PORT'))
+ except TypeError:
+ log.critical(f"DB_PORT variable not set properly")
+ sys.exit(3)
+ DB_USER: str = os.getenv('DB_USER')
+ DB_PASSWD: str = os.getenv('DB_PASSWD')
+ DB_NAME: str = os.getenv('DB_NAME', 'romm')
+
+ return f"mariadb+mariadbconnector://{DB_USER}:%s@{DB_HOST}:{DB_PORT}/{DB_NAME}" % quote_plus(DB_PASSWD)
+
+ elif ROMM_DB_DRIVER == 'sqlite':
+ if not os.path.exists(SQLITE_DB_BASE_PATH): os.makedirs(SQLITE_DB_BASE_PATH)
+ return f"sqlite:////{SQLITE_DB_BASE_PATH}/romm.db"
+
+ else:
+ log.critical(f"{ROMM_DB_DRIVER} database not supported")
+ sys.exit(3)
diff --git a/backend/src/endpoints/platform.py b/backend/src/endpoints/platform.py
new file mode 100644
index 000000000..30642ec42
--- /dev/null
+++ b/backend/src/endpoints/platform.py
@@ -0,0 +1,12 @@
+from fastapi import APIRouter
+
+from handler import dbh
+
+router = APIRouter()
+
+
+@router.get("/platforms", status_code=200)
+def platforms() -> dict:
+ """Returns platforms data"""
+
+ return {'data': dbh.get_platforms()}
diff --git a/backend/src/endpoints/rom.py b/backend/src/endpoints/rom.py
new file mode 100644
index 000000000..58b1c5493
--- /dev/null
+++ b/backend/src/endpoints/rom.py
@@ -0,0 +1,63 @@
+from fastapi import APIRouter, Request, status, HTTPException
+
+from logger.logger import log
+from handler import dbh
+from utils import fs, get_file_name_with_no_tags
+from utils.exceptions import RomNotFoundError, RomAlreadyExistsException
+from models.rom import Rom
+from models.platform import Platform
+
+router = APIRouter()
+
+
+@router.get("/platforms/{p_slug}/roms/{id}", status_code=200)
+def rom(id: int) -> dict:
+ """Returns one rom data of the desired platform"""
+
+ return {'data': dbh.get_rom(id)}
+
+
+@router.get("/platforms/{p_slug}/roms", status_code=200)
+def roms(p_slug: str) -> dict:
+ """Returns all roms of the desired platform"""
+
+ return {'data': dbh.get_roms(p_slug)}
+
+
+@router.patch("/platforms/{p_slug}/roms/{id}", status_code=200)
+async def updateRom(req: Request, p_slug: str, id: int) -> dict:
+ """Updates rom details"""
+
+ data: dict = await req.json()
+ updated_rom: dict = data['updatedRom']
+ db_rom: Rom = dbh.get_rom(id)
+ platform: Platform = dbh.get_platform(p_slug)
+ try:
+ fs.rename_rom(platform.fs_slug, db_rom.file_name, updated_rom['file_name'])
+ except RomAlreadyExistsException as e:
+ error: str = f"{e}"
+ log.error(error)
+ raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=error)
+ updated_rom['file_name_no_tags'] = get_file_name_with_no_tags(updated_rom['file_name'])
+ updated_rom.update(fs.get_cover_details(True, p_slug, updated_rom['file_name'], updated_rom['url_cover']))
+ dbh.update_rom(id, updated_rom)
+ return {'data': dbh.get_rom(id), 'msg': f"{updated_rom['file_name']} updated successfully!"}
+
+
+@router.delete("/platforms/{p_slug}/roms/{id}", status_code=200)
+def delete_rom(p_slug: str, id: int, filesystem: bool=False) -> dict:
+ """Detele rom from database [and filesystem]"""
+
+ rom: Rom = dbh.get_rom(id)
+ log.info(f"Deleting {rom.file_name} from database")
+ dbh.delete_rom(id)
+ if filesystem:
+ log.info(f"Deleting {rom.file_name} from filesystem")
+ try:
+ platform: Platform = dbh.get_platform(p_slug)
+ fs.remove_rom(platform.fs_slug, rom.file_name)
+ except RomNotFoundError as e:
+ error: str = f"{e}. Couldn't delete from filesystem."
+ log.error(error)
+ raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error)
+ return {'msg': f'{rom.file_name} deleted successfully!'}
diff --git a/backend/src/endpoints/scan.py b/backend/src/endpoints/scan.py
new file mode 100644
index 000000000..9878224cd
--- /dev/null
+++ b/backend/src/endpoints/scan.py
@@ -0,0 +1,56 @@
+from fastapi import APIRouter, status, HTTPException
+import emoji
+import json
+
+from logger.logger import log, COLORS
+from config import user_config
+from utils import fs, fastapi
+from utils.exceptions import PlatformsNotFoundException, RomsNotFoundException
+from handler import dbh
+from models.platform import Platform
+from models.rom import Rom
+
+router = APIRouter()
+
+
+@router.get("/scan", status_code=200)
+def scan(platforms: str, full_scan: bool=False) -> dict:
+ """Scan platforms and roms and write them in database."""
+
+ log.info(emoji.emojize(":magnifying_glass_tilted_right: Scanning "))
+ fs.store_default_resources()
+
+ # Scanning platforms
+ try:
+ fs_platforms: list[str] = fs.get_platforms()
+ except PlatformsNotFoundException as e:
+ error: str = f"{e}"
+ log.warning(error)
+ raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error)
+
+ platforms: list[str] = json.loads(platforms) if len(json.loads(platforms)) > 0 else fs_platforms
+ log.info(f"Platforms to be scanned: {', '.join(platforms)}")
+ for platform in platforms:
+ log.info(emoji.emojize(f":video_game: {platform} {COLORS['reset']}"))
+ scanned_platform: Platform = fastapi.scan_platform(platform)
+ if platform != str(scanned_platform): log.info(f"Identified as {COLORS['blue']}{scanned_platform}{COLORS['reset']}")
+ dbh.add_platform(scanned_platform)
+
+ # Scanning roms
+ try:
+ fs_roms: list[str] = fs.get_roms(scanned_platform.fs_slug)
+ except RomsNotFoundException as e:
+ error: str = f"{e}"
+ log.warning(error)
+ raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error)
+ for rom in fs_roms:
+ if rom['multi']: [log.info(f"\t - {COLORS['orange_i']}{file}{COLORS['reset']}") for file in rom['files']]
+ rom_id: int = dbh.rom_exists(rom['file_name'], scanned_platform.slug)
+ if rom_id and not full_scan: continue
+ log.info(f"Scanning {COLORS['orange']}{rom['file_name']}{COLORS['reset']}")
+ scanned_rom: Rom = fastapi.scan_rom(scanned_platform, rom)
+ if rom_id: scanned_rom.id = rom_id
+ dbh.add_rom(scanned_rom)
+ dbh.purge_roms(scanned_platform.slug, [rom['file_name'] for rom in fs_roms])
+ dbh.purge_platforms(fs_platforms)
+ return {'msg': 'Scan completed successfully!'}
\ No newline at end of file
diff --git a/backend/src/endpoints/search.py b/backend/src/endpoints/search.py
new file mode 100644
index 000000000..655027728
--- /dev/null
+++ b/backend/src/endpoints/search.py
@@ -0,0 +1,25 @@
+from fastapi import APIRouter, Request
+import emoji
+
+from logger.logger import log, COLORS
+from handler import igdbh
+
+router = APIRouter()
+
+
+@router.put("/search/roms/igdb", status_code=200)
+async def search_rom_igdb(req: Request, igdb_id: str = None) -> dict:
+ """Get all the roms matched from igdb."""
+
+ data: dict = await req.json()
+ rom: dict = data['rom']
+ log.info(emoji.emojize(":magnifying_glass_tilted_right: IGDB Searching"))
+ if igdb_id:
+ log.info(f"Searching by id: {igdb_id}")
+ matched_roms = igdbh.get_matched_roms_by_id(igdb_id)
+ else:
+ log.info(emoji.emojize(f":video_game: {rom['p_slug']}: {COLORS['orange']}{rom['file_name']}{COLORS['reset']}"))
+ matched_roms = igdbh.get_matched_roms(rom['file_name'], rom['p_igdb_id'], rom['p_slug'])
+ log.info("Results:")
+ [log.info(f"\t - {COLORS['blue']}{rom['r_name']}{COLORS['reset']}") for rom in matched_roms]
+ return {'data': matched_roms, 'msg': 'success'}
diff --git a/backend/src/handler/db_handler.py b/backend/src/handler/db_handler.py
index c139c1f74..14d9011df 100644
--- a/backend/src/handler/db_handler.py
+++ b/backend/src/handler/db_handler.py
@@ -1,12 +1,12 @@
import functools
-from fastapi import HTTPException
-from sqlalchemy import create_engine
+from fastapi import status, HTTPException
+from sqlalchemy import create_engine, select, or_
from sqlalchemy.orm import sessionmaker
-from sqlalchemy import select
from sqlalchemy.exc import ProgrammingError
-from config.config_loader import get_db_engine
+from logger.logger import log
+from config.config_loader import ConfigLoader
from models.platform import Platform
from models.rom import Rom
@@ -14,7 +14,8 @@
class DBHandler:
def __init__(self) -> None:
- self.engine = create_engine(get_db_engine(), pool_pre_ping=True)
+ cl = ConfigLoader()
+ self.engine = create_engine(cl.get_db_engine(), pool_pre_ping=True)
self.session = sessionmaker(bind=self.engine, expire_on_commit=False)
@@ -25,54 +26,108 @@ def wrapper(*args):
return wrapper
+ @staticmethod
+ def raise_error(e: Exception) -> None:
+ error: str = f"{e}"
+ log.critical(error)
+ raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=error)
+
+
# ========= Platforms =========
def add_platform(self, Platform: Platform) -> None:
try:
with self.session.begin() as s:
s.merge(Platform)
except ProgrammingError as e:
- raise HTTPException(status_code=404, detail=f"Platforms table not found: {e}")
+ self.raise_error(e)
+
def get_platforms(self) -> list[Platform]:
try:
with self.session.begin() as s:
return s.scalars(select(Platform).order_by(Platform.slug.asc())).all()
except ProgrammingError as e:
- raise HTTPException(status_code=404, detail=f"Platforms table not found: {e}")
+ self.raise_error(e)
+
+
+ def get_platform(self, slug: str) -> Platform:
+ try:
+ with self.session.begin() as s:
+ return s.scalars(select(Platform).filter_by(slug=slug)).first()
+ except ProgrammingError as e:
+ self.raise_error(e)
+
def purge_platforms(self, platforms: list[str]) -> None:
- with self.session.begin() as s:
- s.query(Platform) \
- .filter(Platform.slug.not_in(platforms)) \
- .delete(synchronize_session='evaluate')
+ try:
+ with self.session.begin() as s:
+ s.query(Platform) \
+ .filter(or_(Platform.fs_slug.not_in(platforms),
+ Platform.fs_slug.is_(None))) \
+ .delete(synchronize_session='evaluate')
+ except ProgrammingError as e:
+ self.raise_error(e)
+
# ========= Roms =========
def add_rom(self, rom: Rom) -> None:
- with self.session.begin() as s:
- s.merge(rom)
+ try:
+ with self.session.begin() as s:
+ s.merge(rom)
+ except ProgrammingError as e:
+ self.raise_error(e)
+
def get_roms(self, p_slug: str) -> list[Rom]:
- with self.session.begin() as s:
- return s.scalars(select(Rom).filter_by(p_slug=p_slug).order_by(Rom.file_name.asc())).all()
-
- def get_rom(self, p_slug: str, file_name: str) -> Rom:
- with self.session.begin() as s:
- return s.scalars(select(Rom).filter_by(p_slug=p_slug, file_name=file_name)).first()
-
- def update_rom(self, p_slug: str, file_name: str, data: dict) -> None:
- with self.session.begin() as s:
- s.query(Rom) \
- .filter(Rom.p_slug==p_slug, Rom.file_name==file_name) \
- .update(data, synchronize_session='evaluate')
-
- def delete_rom(self, p_slug: str, file_name: str) -> None:
- with self.session.begin() as s:
- s.query(Rom) \
- .filter(Rom.p_slug==p_slug, Rom.file_name==file_name) \
- .delete(synchronize_session='evaluate')
-
- def purge_roms(self, p_slug: str, roms: list[dict]) -> None:
- with self.session.begin() as s:
- s.query(Rom) \
- .filter(Rom.p_slug==p_slug, Rom.file_name.not_in([rom['file_name'] for rom in roms])) \
- .delete(synchronize_session='evaluate')
+ try:
+ with self.session.begin() as s:
+ return s.scalars(select(Rom).filter_by(p_slug=p_slug).order_by(Rom.file_name.asc())).all()
+ except ProgrammingError as e:
+ self.raise_error(e)
+
+
+ def get_rom(self, id) -> Rom:
+ try:
+ with self.session.begin() as s:
+ return s.scalars(select(Rom).filter_by(id=id)).first()
+ except ProgrammingError as e:
+ self.raise_error(e)
+
+
+ def update_rom(self, id: int, data: dict) -> None:
+ try:
+ with self.session.begin() as s:
+ s.query(Rom) \
+ .filter(Rom.id==id).update(data, synchronize_session='evaluate')
+ except ProgrammingError as e:
+ self.raise_error(e)
+
+
+ def delete_rom(self, id: int) -> None:
+ try:
+ with self.session.begin() as s:
+ s.query(Rom) \
+ .filter(Rom.id==id).delete(synchronize_session='evaluate')
+ except ProgrammingError as e:
+ self.raise_error(e)
+
+
+ def purge_roms(self, p_slug: str, roms: list[str]) -> None:
+ try:
+ with self.session.begin() as s:
+ s.query(Rom) \
+ .filter(Rom.p_slug==p_slug, Rom.file_name.not_in(roms)) \
+ .delete(synchronize_session='evaluate')
+ except ProgrammingError as e:
+ self.raise_error(e)
+
+
+ # ==== Utils ======
+ def rom_exists(self, file_name: str, platform: str) -> int:
+ db_roms: list = self.get_roms(platform)
+ rom_id: int = 0
+ for db_rom in db_roms:
+ if db_rom.file_name == file_name:
+ rom_id = db_rom.id
+ break
+ return rom_id
\ No newline at end of file
diff --git a/backend/src/handler/igdb_handler.py b/backend/src/handler/igdb_handler.py
index 64e0125ae..dd6f67f10 100644
--- a/backend/src/handler/igdb_handler.py
+++ b/backend/src/handler/igdb_handler.py
@@ -1,12 +1,11 @@
import sys
import functools
-import re
import unidecode
from time import time
import requests
-
from config import CLIENT_ID, CLIENT_SECRET, DEFAULT_URL_COVER_L
+from utils import get_file_name_with_no_tags
from logger.logger import log
@@ -46,10 +45,10 @@ def get_platform_details(self, slug: str) -> tuple:
@check_twitch_token
def get_rom_details(self, file_name: str, p_igdb_id: int, r_igdb_id_search: str) -> dict:
- file_name_no_tags: str = re.sub('[\(\[].*?[\)\]]', '', file_name.split('.')[0])
+ search_term: str = unidecode.unidecode(get_file_name_with_no_tags(file_name))
r_igdb_id: str = ""
- slug: str = ""
- name: str = ""
+ r_slug: str = ""
+ r_name: str = ""
summary: str = ""
url_cover: str = ""
@@ -57,23 +56,21 @@ def get_rom_details(self, file_name: str, p_igdb_id: int, r_igdb_id_search: str)
res_details: dict = requests.post("https://api.igdb.com/v4/games/", headers=self.headers,
data=f"fields id, slug, name, summary; where id={r_igdb_id_search};").json()[0]
r_igdb_id = res_details['id']
- slug = res_details['slug']
- name = res_details['name']
+ r_slug = res_details['slug']
+ r_name = res_details['name']
try:
summary = res_details['summary']
except KeyError:
pass
else: #TODO: improve API calls to make only one
- search_term: str = unidecode.unidecode(file_name_no_tags)
if p_igdb_id:
try:
-
res_details: dict = requests.post("https://api.igdb.com/v4/games/", headers=self.headers,
data=f"search \"{search_term}\";fields id, slug, name, summary; where platforms=[{p_igdb_id}] & category=0;").json()[0]
r_igdb_id = res_details['id']
- slug = res_details['slug']
- name = res_details['name']
+ r_slug = res_details['slug']
+ r_name = res_details['name']
try:
summary = res_details['summary']
except KeyError:
@@ -83,8 +80,8 @@ def get_rom_details(self, file_name: str, p_igdb_id: int, r_igdb_id_search: str)
res_details: dict = requests.post("https://api.igdb.com/v4/games/", headers=self.headers,
data=f"search \"{search_term}\";fields name, id, slug, summary; where platforms=[{p_igdb_id}] & category=10;").json()[0]
r_igdb_id = res_details['id']
- slug = res_details['slug']
- name = res_details['name']
+ r_slug = res_details['slug']
+ r_name = res_details['name']
try:
summary = res_details['summary']
except KeyError:
@@ -94,8 +91,8 @@ def get_rom_details(self, file_name: str, p_igdb_id: int, r_igdb_id_search: str)
res_details: dict = requests.post("https://api.igdb.com/v4/games/", headers=self.headers,
data=f"search \"{search_term}\";fields name, id, slug, summary; where platforms=[{p_igdb_id}];").json()[0]
r_igdb_id = res_details['id']
- slug = res_details['slug']
- name = res_details['name']
+ r_slug = res_details['slug']
+ r_name = res_details['name']
try:
summary = res_details['summary']
except KeyError:
@@ -108,16 +105,16 @@ def get_rom_details(self, file_name: str, p_igdb_id: int, r_igdb_id_search: str)
data=f"fields url; where game={r_igdb_id};").json()[0]
url_cover: str = f"https:{res_details['url']}"
except IndexError:
- log.warning(f"{name} cover not found in IGDB")
- if not name: name = file_name_no_tags
- return (r_igdb_id, file_name_no_tags, slug, name, summary, url_cover)
+ log.warning(f"{r_name} cover not found in IGDB")
+ if not r_name: r_name = search_term
+ return {'r_igdb_id': r_igdb_id, 'r_slug': r_slug, 'r_name': r_name, 'summary': summary, 'url_cover': url_cover}
@check_twitch_token
def get_matched_roms(self, file_name: str, p_igdb_id: int, p_slug: str) -> list:
matched_roms: list[dict] = []
if p_igdb_id != '':
- search_term: str = unidecode.unidecode(re.sub('[\(\[].*?[\)\]]', '', file_name.split('.')[0]))
+ search_term: str = unidecode.unidecode(get_file_name_with_no_tags(file_name))
matched_roms: list = requests.post("https://api.igdb.com/v4/games/", headers=self.headers,
data=f"search \"{search_term}\";fields name, id, slug, summary; where platforms=[{p_igdb_id}];").json()
for rom in matched_roms:
@@ -129,23 +126,29 @@ def get_matched_roms(self, file_name: str, p_igdb_id: int, p_slug: str) -> list:
rom['url_cover'] = DEFAULT_URL_COVER_L
rom['r_igdb_id'] = rom.pop('id')
rom['r_slug'] = rom.pop('slug')
+ rom['r_name'] = rom.pop('name')
else:
log.warning(f"{p_slug} is not supported!")
return matched_roms
+
def get_matched_roms_by_id(self, igdb_id: str) -> list:
- matched_roms: list[dict] = []
- matched_roms: list = requests.post("https://api.igdb.com/v4/games/", headers=self.headers,
- data=f"fields name, id, slug, summary; where id={igdb_id};").json()
- for rom in matched_roms:
- try:
- res_details: dict = requests.post("https://api.igdb.com/v4/covers/", headers=self.headers,
- data=f"fields url; where game={rom['id']};").json()[0]
- rom['url_cover'] = f"https:{res_details['url']}".replace('t_thumb', f't_cover_big')
- except IndexError:
- rom['url_cover'] = DEFAULT_URL_COVER_L
- rom['r_igdb_id'] = rom.pop('id')
- rom['r_slug'] = rom.pop('slug')
+ res: list = requests.post("https://api.igdb.com/v4/games/", headers=self.headers,
+ data=f"fields name, id, slug, summary; where id={igdb_id};")
+ if res.status_code == 200:
+ matched_roms = res.json()
+ for rom in matched_roms:
+ try:
+ res_details: dict = requests.post("https://api.igdb.com/v4/covers/", headers=self.headers,
+ data=f"fields url; where game={rom['id']};").json()[0]
+ rom['url_cover'] = f"https:{res_details['url']}".replace('t_thumb', f't_cover_big')
+ except IndexError:
+ rom['url_cover'] = DEFAULT_URL_COVER_L
+ rom['r_igdb_id'] = rom.pop('id')
+ rom['r_slug'] = rom.pop('slug')
+ rom['r_name'] = rom.pop('name')
+ else:
+ matched_roms: list = []
return matched_roms
diff --git a/backend/src/main.py b/backend/src/main.py
index 27ac9d05d..37db73aae 100644
--- a/backend/src/main.py
+++ b/backend/src/main.py
@@ -1,17 +1,22 @@
-from fastapi import FastAPI, Request
+from fastapi import FastAPI
+from fastapi.middleware.cors import CORSMiddleware
import uvicorn
-import json
-import emoji
-from logger.logger import log, COLORS
-from handler import igdbh, dbh
from config import DEV_PORT, DEV_HOST
-from models.platform import Platform
-from utils import fs, fastapi
-
+from endpoints import scan, search, platform, rom
app = FastAPI()
-fastapi.allow_cors(app)
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=["*"],
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+)
+app.include_router(scan.router)
+app.include_router(search.router)
+app.include_router(platform.router)
+app.include_router(rom.router)
@app.on_event("startup")
@@ -20,113 +25,5 @@ def startup() -> None:
pass
-@app.get("/scan")
-def scan(platforms: str, full_scan: bool=False) -> dict:
- """Scan platforms and roms and write them in database."""
-
- log.info(emoji.emojize(":magnifying_glass_tilted_right: Scanning "))
- fs.store_default_resources()
- fs_platforms: list[str] = fs.get_platforms()
- platforms: list[str] = json.loads(platforms) if len(json.loads(platforms)) > 0 else fs_platforms
- log.info(f"Platforms to be scanned: {', '.join(platforms)}")
- for p_slug in platforms:
- log.info(emoji.emojize(f":video_game: {p_slug} {COLORS['reset']}"))
- platform: Platform = fastapi.scan_platform(p_slug)
- if p_slug != str(platform): log.info(f"Identified as {COLORS['blue']}{platform}{COLORS['reset']}")
- dbh.add_platform(platform)
- log.info(f"Searching new roms")
- roms: list[dict] = fs.get_roms(p_slug, full_scan)
- for rom in roms:
- log.info(f"Getting {COLORS['orange']}{rom['file_name']}{COLORS['reset']} details")
- if rom['multi']: [log.info(f"\t - {COLORS['orange_i']}{file}{COLORS['reset']}") for file in rom['files']]
- rom = fastapi.scan_rom(platform, rom)
- dbh.add_rom(rom)
- log.info(emoji.emojize(":wastebasket: Purging database"))
- [dbh.purge_roms(p_slug, fs.get_roms(p_slug, True)) for p_slug in platforms]
- dbh.purge_platforms(fs_platforms)
- return {'msg': 'success'}
-
-
-@app.get("/platforms")
-def platforms() -> dict:
- """Returns platforms data"""
-
- return {'data': dbh.get_platforms()}
-
-
-@app.get("/platforms/{p_slug}/roms/{file_name}")
-def rom(p_slug: str, file_name: str) -> dict:
- """Returns one rom data of the desired platform"""
-
- return {'data': dbh.get_rom(p_slug, file_name)}
-
-
-@app.get("/platforms/{p_slug}/roms")
-def roms(p_slug: str) -> dict:
- """Returns all roms of the desired platform"""
-
- return {'data': dbh.get_roms(p_slug)}
-
-
-@app.patch("/platforms/{p_slug}/roms")
-async def updateRom(req: Request, p_slug: str) -> dict:
- """Updates rom details"""
-
- data: dict = await req.json()
- rom: dict = data['rom']
- updatedRom: dict = data['updatedRom']
- log.info(f"Updating {COLORS['orange']}{updatedRom['file_name']}{COLORS['reset']} details")
- r_igdb_id, file_name_no_tags, r_slug, r_name, summary, url_cover = igdbh.get_rom_details(updatedRom['file_name'], rom['p_igdb_id'], updatedRom['r_igdb_id'])
- path_cover_s, path_cover_l, has_cover = fs.get_cover_details(True, p_slug, updatedRom['file_name'], url_cover)
- updatedRom['file_name_no_tags'] = file_name_no_tags
- updatedRom['r_igdb_id'] = r_igdb_id
- updatedRom['p_igdb_id'] = rom['p_igdb_id']
- updatedRom['r_slug'] = r_slug
- updatedRom['p_slug'] = p_slug
- updatedRom['name'] = r_name
- updatedRom['summary'] = summary
- updatedRom['path_cover_s'] = path_cover_s
- updatedRom['path_cover_l'] = path_cover_l
- updatedRom['has_cover'] = has_cover
- updatedRom['file_path'] = rom['file_path']
- updatedRom['file_size'] = rom['file_size']
- updatedRom['file_extension'] = updatedRom['file_name'].split('.')[-1] if '.' in updatedRom['file_name'] else ""
- reg, rev, other_tags = fs.parse_tags(updatedRom['file_name'])
- updatedRom.update({'region': reg, 'revision': rev, 'tags': other_tags})
- if 'url_cover' in updatedRom.keys(): del updatedRom['url_cover']
- fs.rename_rom(p_slug, rom['file_name'], updatedRom['file_name'])
- dbh.update_rom(p_slug, rom['file_name'], updatedRom)
- return {'data': updatedRom}
-
-
-@app.delete("/platforms/{p_slug}/roms/{file_name}")
-def remove_rom(p_slug: str, file_name: str, filesystem: bool=False) -> dict:
- """Detele rom from filesystem and database"""
-
- log.info(f"Deleting {file_name} from database")
- dbh.delete_rom(p_slug, file_name)
- if filesystem:
- log.info(f"Removing {file_name} from filesystem")
- fs.remove_rom(p_slug, file_name)
- return {'msg': 'success'}
-
-
-@app.put("/search/roms/igdb")
-async def search_rom_igdb(req: Request, igdb_id: str=None) -> dict:
- """Get all the roms matched from igdb."""
-
- data: dict = await req.json()
- log.info(emoji.emojize(":magnifying_glass_tilted_right: IGDB Searching"))
- if igdb_id:
- log.info(f"Searching by id: {igdb_id}")
- matched_roms = igdbh.get_matched_roms_by_id(igdb_id)
- else:
- log.info(emoji.emojize(f":video_game: {data['rom']['p_slug']}: {COLORS['orange']}{data['rom']['file_name']}{COLORS['reset']}"))
- matched_roms = igdbh.get_matched_roms(data['rom']['file_name'], data['rom']['p_igdb_id'], data['rom']['p_slug'])
- log.info("Results:")
- [log.info(f"\t - {COLORS['blue']}{rom['name']}{COLORS['reset']}") for rom in matched_roms]
- return {'data': matched_roms}
-
-
if __name__ == '__main__':
uvicorn.run("main:app", host=DEV_HOST, port=DEV_PORT, reload=True)
diff --git a/backend/src/models/platform.py b/backend/src/models/platform.py
index e861f867b..0b60c0bf0 100644
--- a/backend/src/models/platform.py
+++ b/backend/src/models/platform.py
@@ -9,12 +9,14 @@ class Platform(BaseModel):
igdb_id = Column(String(length=10), default="")
sgdb_id = Column(String(length=10), default="")
- slug = Column(String(length=50), primary_key=True)
+ slug = Column(String(length=50), default="")
name = Column(String(length=400), default="")
logo_path = Column(String(length=1000), default=DEFAULT_PATH_COVER_S)
n_roms = Column(Integer, default=0)
+ fs_slug = Column(String(length=50), primary_key=True)
+
def __repr__(self) -> str:
return self.name
diff --git a/backend/src/models/rom.py b/backend/src/models/rom.py
index d499ae1b6..20cbcf685 100644
--- a/backend/src/models/rom.py
+++ b/backend/src/models/rom.py
@@ -1,4 +1,4 @@
-from sqlalchemy import Column, String, Text, Boolean, Float, JSON
+from sqlalchemy import Integer, Column, String, Text, Boolean, Float, JSON
from config import DEFAULT_PATH_COVER_S, DEFAULT_PATH_COVER_L
from models.base import BaseModel
@@ -6,21 +6,24 @@
class Rom(BaseModel):
__tablename__ = 'roms'
+ id = Column(Integer(), primary_key=True, autoincrement=True)
+
r_igdb_id = Column(String(length=10), default="")
p_igdb_id = Column(String(length=10), default="")
r_sgdb_id = Column(String(length=10), default="")
p_sgdb_id = Column(String(length=10), default="")
- p_slug = Column(String(length=50), primary_key=True)
+ p_slug = Column(String(length=50))
+ p_name = Column(String(length=150), default="")
- file_name = Column(String(length=450), primary_key=True)
- file_name_no_tags = Column(String(length=450), default="")
+ file_name = Column(String(length=450))
+ file_name_no_tags = Column(String(length=450))
file_extension = Column(String(length=10), default="")
file_path = Column(String(length=1000), default="")
file_size = Column(Float, default=0.0)
file_size_units = Column(String(length=10), default="")
- name = Column(String(length=350), default="")
+ r_name = Column(String(length=350), default="")
r_slug = Column(String(length=100), default="")
summary = Column(Text, default="")
@@ -28,6 +31,7 @@ class Rom(BaseModel):
path_cover_s = Column(Text, default=DEFAULT_PATH_COVER_S)
path_cover_l = Column(Text, default=DEFAULT_PATH_COVER_L)
has_cover = Column(Boolean, default=False)
+ url_cover = Column(Text, default=DEFAULT_PATH_COVER_L)
region = Column(String(20), default="")
revision = Column(String(20), default="")
diff --git a/backend/src/utils/__init__.py b/backend/src/utils/__init__.py
index e69de29bb..2bddd075f 100644
--- a/backend/src/utils/__init__.py
+++ b/backend/src/utils/__init__.py
@@ -0,0 +1,26 @@
+import re
+
+
+def parse_tags(file_name: str) -> tuple:
+ reg: str = ''
+ rev: str = ''
+ other_tags: list = []
+ tags: list = re.findall('\(([^)]+)', file_name)
+ for tag in tags:
+ if tag.split('-')[0].lower() == 'reg':
+ try: reg = tag.split('-', 1)[1]
+ except IndexError: pass
+ elif tag.split('-')[0].lower() == 'rev':
+ try: rev = tag.split('-', 1)[1]
+ except IndexError: pass
+ else:
+ other_tags.append(tag)
+ return reg, rev, other_tags
+
+
+def get_file_name_with_no_tags(file_name: str) -> str:
+ return re.sub('[\(\[].*?[\)\]]', '', file_name.split('.')[0])
+
+
+def get_file_extension(rom: dict) -> str:
+ return rom['file_name'].split('.')[-1] if not rom['multi'] else ''
diff --git a/backend/src/utils/exceptions.py b/backend/src/utils/exceptions.py
new file mode 100644
index 000000000..9d29e26fd
--- /dev/null
+++ b/backend/src/utils/exceptions.py
@@ -0,0 +1,34 @@
+class PlatformsNotFoundException(Exception):
+ def __init__(self):
+ self.message = f"Platforms not found"
+ super().__init__(self.message)
+
+ def __repr__(self) -> str:
+ return self.message
+
+
+class RomsNotFoundException(Exception):
+ def __init__(self, platform: str):
+ self.message = f"Roms not found for platform {platform}"
+ super().__init__(self.message)
+
+ def __repr__(self) -> str:
+ return self.message
+
+
+class RomNotFoundError(Exception):
+ def __init__(self, rom: str, platform: str):
+ self.message = f"Rom {rom} not found for platform {platform}"
+ super().__init__(self.message)
+
+ def __repr__(self) -> str:
+ return self.message
+
+
+class RomAlreadyExistsException(Exception):
+ def __init__(self, rom_name: str):
+ self.message = f"Can't rename: {rom_name} already exists"
+ super().__init__(self.message)
+
+ def __repr__(self) -> str:
+ return self.message
\ No newline at end of file
diff --git a/backend/src/utils/fastapi.py b/backend/src/utils/fastapi.py
index a0eff8327..b9d361e86 100644
--- a/backend/src/utils/fastapi.py
+++ b/backend/src/utils/fastapi.py
@@ -1,49 +1,47 @@
-from fastapi import FastAPI
-from fastapi.middleware.cors import CORSMiddleware
-
from handler import igdbh
-from utils import fs
+from utils import fs, parse_tags, get_file_extension, get_file_name_with_no_tags
+from config import user_config
+from logger.logger import log
from models.platform import Platform
from models.rom import Rom
-from logger.logger import log
-def allow_cors(app: FastAPI) -> None:
- app.add_middleware(
- CORSMiddleware,
- allow_origins=["*"],
- allow_credentials=True,
- allow_methods=["*"],
- allow_headers=["*"],
- )
-
-
-def scan_platform(p_slug: str) -> Platform:
- """Get platform details from IGDB if possible
+def scan_platform(fs_slug: str) -> Platform:
+ """Get platform details
Args:
p_slug: short name of the platform
Returns
Platform object
"""
- platform_attrs: dict = igdbh.get_platform_details(p_slug)
- platform_attrs['n_roms'] = fs.get_roms(p_slug, True, only_amount=True)
+
+ platform_attrs: dict = {}
+ platform_attrs['fs_slug'] = fs_slug
+ try:
+ if fs_slug in user_config['system']['platforms'].keys():
+ platform_attrs['slug'] = user_config['system']['platforms'][fs_slug]
+ else:
+ platform_attrs['slug'] = fs_slug
+ except (KeyError, TypeError, AttributeError):
+ platform_attrs['slug'] = fs_slug
+ platform_attrs.update(igdbh.get_platform_details(platform_attrs['slug']))
+ platform_attrs['n_roms'] = len(fs.get_roms(platform_attrs['fs_slug']))
platform = Platform(**platform_attrs)
return platform
-def scan_rom(platform: Platform, rom: dict, r_igbd_id_search: str = '', overwrite: bool = False) -> None:
- r_igdb_id, file_name_no_tags, r_slug, r_name, summary, url_cover = igdbh.get_rom_details(rom['file_name'], platform.igdb_id, r_igbd_id_search)
- path_cover_s, path_cover_l, has_cover = fs.get_cover_details(overwrite, platform.slug, rom['file_name'], url_cover)
- rom['file_name_no_tags'] = file_name_no_tags
- rom['r_igdb_id'] = r_igdb_id
- rom['p_igdb_id'] = platform.igdb_id
- rom['r_slug'] = r_slug
- rom['p_slug'] = platform.slug
- rom['name'] = r_name
- rom['summary'] = summary
- rom['path_cover_s'] = path_cover_s
- rom['path_cover_l'] = path_cover_l
- rom['has_cover'] = has_cover
- rom = Rom(**rom)
+def scan_rom(platform: Platform, rom_attrs: dict, r_igbd_id_search: str = '', overwrite: bool = False) -> Rom:
+ p_slug: str = platform.fs_slug if platform.fs_slug else platform.slug
+ roms_path: str = fs.get_roms_structure(p_slug)
+ rom_attrs.update(igdbh.get_rom_details(rom_attrs['file_name'], platform.igdb_id, r_igbd_id_search))
+ rom_attrs.update(fs.get_cover_details(overwrite, platform.slug, rom_attrs['file_name'], rom_attrs['url_cover']))
+ file_size, file_size_units = fs.get_rom_size(rom_attrs['multi'], rom_attrs['file_name'], rom_attrs['files'], roms_path)
+ reg, rev, other_tags = parse_tags(rom_attrs['file_name'])
+ rom_attrs.update({'file_path': roms_path, 'file_name': rom_attrs['file_name'], 'file_name_no_tags': get_file_name_with_no_tags(rom_attrs['file_name']),
+ 'file_extension': get_file_extension(rom_attrs), 'file_size': file_size, 'file_size_units': file_size_units,
+ 'multi': rom_attrs['multi'], 'region': reg, 'revision': rev, 'tags': other_tags})
+ rom_attrs['p_igdb_id'] = platform.igdb_id
+ rom_attrs['p_slug'] = platform.slug
+ rom_attrs['p_name'] = platform.name
+ rom = Rom(**rom_attrs)
return rom
diff --git a/backend/src/utils/fs.py b/backend/src/utils/fs.py
index 9e3bb929d..61e3949ce 100644
--- a/backend/src/utils/fs.py
+++ b/backend/src/utils/fs.py
@@ -1,17 +1,79 @@
import os
import shutil
-import re
from pathlib import Path
import requests
-from fastapi import HTTPException
from config import user_config, LIBRARY_BASE_PATH, HIGH_PRIO_STRUCTURE_PATH, RESOURCES_BASE_PATH, DEFAULT_URL_COVER_L, DEFAULT_PATH_COVER_L, DEFAULT_URL_COVER_S, DEFAULT_PATH_COVER_S
-from handler import dbh
from logger.logger import log
+from utils.exceptions import PlatformsNotFoundException, RomsNotFoundException, RomNotFoundError, RomAlreadyExistsException
+
+
+# ========= Resources utils =========
+def _cover_exists(p_slug: str, file_name: str, size: str) -> bool:
+ """Check if rom cover exists in filesystem
+
+ Args:
+ p_slug: short name of the platform
+ file_name: name of rom file
+ size: size of the cover -> big as 'l' | small as 's'
+ Returns
+ True if cover exists in filesystem else False
+ """
+ logo_path: str = f"{RESOURCES_BASE_PATH}/{p_slug}/{file_name}_{size}.png"
+ return True if os.path.exists(logo_path) else False
+
+
+def _store_cover(p_slug: str, file_name: str, url_cover: str, size: str) -> None:
+ """Store roms resources in filesystem
+
+ Args:
+ p_slug: short name of the platform
+ file_name: name of rom file
+ url_cover: url to get the cover
+ size: size of the cover -> big as 'l' | small as 's'
+ """
+ cover_file: str = f"{file_name}_{size}.png"
+ cover_path: str = f"{RESOURCES_BASE_PATH}/{p_slug}/"
+ sizes: dict = {'l': 'big', 's': 'small'}
+ res = requests.get(url_cover.replace('t_thumb', f't_cover_{sizes[size]}'), stream=True)
+ if res.status_code == 200:
+ Path(cover_path).mkdir(parents=True, exist_ok=True)
+ with open(f"{cover_path}/{cover_file}", 'wb') as f:
+ shutil.copyfileobj(res.raw, f)
+ log.info(f"{file_name} {sizes[size]} cover downloaded successfully!")
+ else:
+ log.error(f"{file_name} {sizes[size]} cover couldn't be downloaded")
+
+
+def _get_cover_path(p_slug: str, file_name: str, size: str) -> str:
+ """Returns rom cover filesystem path adapted to frontend folder structure
+
+ Args:
+ p_slug: short name of the platform
+ file_name: name of rom file
+ size: size of the cover -> big as 'l' | small as 's'
+ """
+ return f"{RESOURCES_BASE_PATH}/{p_slug}/{file_name}_{size}.png"
+
+
+def get_cover_details(overwrite: bool, p_slug: str, file_name: str, url_cover: str) -> tuple:
+ path_cover_s: str = DEFAULT_PATH_COVER_S
+ path_cover_l: str = DEFAULT_PATH_COVER_L
+ has_cover: int = 0
+ if (overwrite or not _cover_exists(p_slug, file_name, 's')) and url_cover:
+ _store_cover(p_slug, file_name, url_cover, 's')
+ if _cover_exists(p_slug, file_name, 's'):
+ path_cover_s = _get_cover_path(p_slug, file_name, 's')
+
+ if (overwrite or not _cover_exists(p_slug, file_name, 'l')) and url_cover:
+ _store_cover(p_slug, file_name, url_cover, 'l')
+ if _cover_exists(p_slug, file_name, 'l'):
+ path_cover_l = _get_cover_path(p_slug, file_name, 'l')
+ has_cover = 1
+ return {'path_cover_s': path_cover_s, 'path_cover_l': path_cover_l, 'has_cover': has_cover}
-# ========= Defaults utils =========
def store_default_resources() -> None:
"""Store default cover resources in the filesystem"""
defaul_covers: dict = [{'url': DEFAULT_URL_COVER_L, 'size': 'l'}, {'url': DEFAULT_URL_COVER_S, 'size': 's'}]
@@ -33,42 +95,55 @@ def get_platforms() -> list[str]:
"""
try:
platforms: list[str] = list(os.walk(HIGH_PRIO_STRUCTURE_PATH))[0][1] if os.path.exists(HIGH_PRIO_STRUCTURE_PATH) else list(os.walk(LIBRARY_BASE_PATH))[0][1]
- try:
- _exclude_platforms(platforms)
- except (KeyError, TypeError):
- pass
- return platforms
except IndexError:
- error: str = "Platforms not found"
- log.critical(error)
- raise HTTPException(status_code=404, detail=error)
+ raise PlatformsNotFoundException
+ try:
+ _exclude_platforms(platforms)
+ except (KeyError, TypeError):
+ pass
+ return platforms
# ========= Roms utils =========
-def _get_roms_structure(p_slug) -> tuple:
+def get_roms_structure(p_slug: str) -> tuple:
return f"{HIGH_PRIO_STRUCTURE_PATH}/{p_slug}" if os.path.exists(HIGH_PRIO_STRUCTURE_PATH) else f"{LIBRARY_BASE_PATH}/{p_slug}/roms"
-def _exclude_single_roms(roms) -> list[str]:
- try:
- excluded_extensions: list = []
- excluded_extensions = user_config['exclude']['roms']['single_file']['extensions']
- except (TypeError, KeyError):
- pass
- try:
- excluded_names: list = []
- excluded_names = user_config['exclude']['roms']['single_file']['names']
- except (TypeError, KeyError):
- pass
+def get_rom_files(rom: str, roms_path: str) -> list[str]:
+ rom_files: list = []
+ for path, _, files in os.walk(f"{roms_path}/{rom}"):
+ [rom_files.append(f"{Path(path, f)}".replace(f"{roms_path}/{rom}/", '')) for f in _exclude_files(files, 'multi')]
+ return rom_files
+
+
+def _exclude_files(files, type) -> list[str]:
+ if type == 'single':
+ try:
+ excluded_extensions = user_config['exclude']['roms'][f'{type}_file']['extensions']
+ except (TypeError, KeyError):
+ excluded_extensions: list = []
+ try:
+ excluded_names = user_config['exclude']['roms'][f'{type}_file']['names']
+ except (TypeError, KeyError):
+ excluded_names: list = []
+ elif type == 'multi':
+ try:
+ excluded_extensions = user_config['exclude']['roms'][f'{type}_file']['parts']['extensions']
+ except (TypeError, KeyError):
+ excluded_extensions: list = []
+ try:
+ excluded_names = user_config['exclude']['roms'][f'{type}_file']['parts']['names']
+ except (TypeError, KeyError):
+ excluded_names: list = []
filtered_files: list = []
- for rom in roms:
+ for file in files:
try:
- if rom.split('.')[-1] in excluded_extensions or rom in excluded_names:
- filtered_files.append(rom)
+ if file.split('.')[-1] in excluded_extensions or file in excluded_names:
+ filtered_files.append(file)
except TypeError:
pass
- roms = [f for f in roms if f not in filtered_files]
- return roms
+ files = [f for f in files if f not in filtered_files]
+ return files
def _exclude_multi_roms(roms) -> list[str]:
@@ -88,99 +163,37 @@ def _exclude_multi_roms(roms) -> list[str]:
return roms
-def _exclude_multi_roms_parts(parts) -> list[str]:
- try:
- excluded_extensions: list = []
- excluded_extensions = user_config['exclude']['roms']['multi_file']['parts']['extensions']
- except (TypeError, KeyError):
- pass
- try:
- excluded_names: list = []
- excluded_names = user_config['exclude']['roms']['multi_file']['parts']['names']
- except (TypeError, KeyError):
- pass
- filtered_files: list = []
- for part in parts:
- try:
- if part.split('.')[-1] in excluded_extensions or part in excluded_names:
- filtered_files.append(part)
- except TypeError:
- log.warning(f"Config file is malformed")
- parts = [f for f in parts if f not in filtered_files]
- return parts
-
-
-def parse_tags(file_name: str) -> tuple:
- reg: str = ''
- rev: str = ''
- other_tags: list = []
- tags: list = re.findall('\(([^)]+)', file_name)
- for tag in tags:
- if tag.split('-')[0].lower() == 'reg':
- try: reg = tag.split('-', 1)[1]
- except IndexError: pass
- elif tag.split('-')[0].lower() == 'rev':
- try: rev = tag.split('-', 1)[1]
- except IndexError: pass
- else:
- other_tags.append(tag)
- return reg, rev, other_tags
-
-
-def _get_file_extension(rom: dict) -> str:
- return rom['file'].split('.')[-1] if not rom['multi'] else ''
-
-
-def _get_rom_files(multi: bool, rom: str, roms_path: str) -> list[str]:
- return [] if not multi else _exclude_multi_roms_parts(list(os.walk(f"{roms_path}/{rom}"))[0][2])
-
-
-def _convert_size_human_readable(size, decimals=2) -> tuple:
- for unit in ['B', 'KB', 'MB', 'GB', 'TB', 'PB']:
- if size < 1024.0 or unit == 'PB': break
- size /= 1024.0
- return round(size, 2), unit
-
-
-def _get_file_size(multi: bool, rom: str, files: list, roms_path:str) -> str:
+def get_rom_size(multi: bool, rom: str, files: list, roms_path:str) -> str:
files: list = [f"{roms_path}/{rom}"] if not multi else [f"{roms_path}/{rom}/{file}" for file in files]
total_size: int = 0
for file in files:
total_size += os.stat(file).st_size
- return _convert_size_human_readable(total_size)
+ for unit in ['B', 'KB', 'MB', 'GB', 'TB', 'PB']:
+ if total_size < 1024.0 or unit == 'PB': break
+ total_size /= 1024.0
+ return round(total_size, 2), unit
-def get_roms(p_slug: str, full_scan: bool, only_amount: bool = False) -> list[dict]:
+def get_roms(p_slug: str) -> list[dict] or int:
"""Gets all filesystem roms for a platform
Args:
p_slug: short name of the platform
- full_scan: flag to get all roms in fs or only new ones
- only_amount: flag to return only amount of roms instead of all info
- Returns: list with all the filesystem roms for a platform found in the LIBRARY_BASE_PATH. Just the amount of them if only_amount=True
+ Returns: list with all the filesystem roms for a platform found in the LIBRARY_BASE_PATH.
"""
- roms_path = _get_roms_structure(p_slug)
- roms: list[dict] = []
-
- db_roms: list[str] = [rom.file_name for rom in dbh.get_roms(p_slug)]
-
- fs_single_roms: list[str] = list(os.walk(roms_path))[0][2]
- fs_multi_roms: list[str] = list(os.walk(roms_path))[0][1]
- fs_roms: list[dict] = [{'multi': False, 'file': rom} for rom in _exclude_single_roms(fs_single_roms)] + \
- [{'multi': True, 'file': rom} for rom in _exclude_multi_roms(fs_multi_roms)]
-
- if only_amount: return len(fs_roms)
-
- for rom in fs_roms:
- if rom['file'] in db_roms and not full_scan and not rom['multi']: continue
- reg, rev, other_tags = parse_tags(rom['file'])
- file_extension: str = _get_file_extension(rom)
- files: list = _get_rom_files(rom['multi'], rom['file'], roms_path)
- file_size, file_size_units = _get_file_size(rom['multi'], rom['file'], files, roms_path)
- roms.append({'file_name': rom['file'], 'file_path': roms_path, 'multi': rom['multi'],
- 'files': files, 'file_size': file_size, 'file_size_units': file_size_units, 'file_extension': file_extension,
- 'region': reg, 'revision': rev, 'tags': other_tags})
- return roms
+ roms_path = get_roms_structure(p_slug)
+ try:
+ fs_single_roms: list[str] = list(os.walk(roms_path))[0][2]
+ except IndexError:
+ raise RomsNotFoundException(p_slug)
+ try:
+ fs_multi_roms: list[str] = list(os.walk(roms_path))[0][1]
+ except IndexError:
+ raise RomsNotFoundException(p_slug)
+ fs_roms: list[dict] = [{'multi': False, 'file_name': rom} for rom in _exclude_files(fs_single_roms, 'single')] + \
+ [{'multi': True, 'file_name': rom} for rom in _exclude_multi_roms(fs_multi_roms)]
+ [rom.update({'files': get_rom_files(rom['file_name'], roms_path)}) for rom in fs_roms]
+ return fs_roms
def _rom_exists(p_slug: str, file_name: str) -> bool:
@@ -192,90 +205,25 @@ def _rom_exists(p_slug: str, file_name: str) -> bool:
Returns
True if rom exists in filesystem else False
"""
- rom_path = _get_roms_structure(p_slug)
+ rom_path = get_roms_structure(p_slug)
exists: bool = True if os.path.exists(f"{rom_path}/{file_name}") else False
return exists
def rename_rom(p_slug: str, old_name: str, new_name: str) -> None:
if new_name != old_name:
- rom_path = _get_roms_structure(p_slug)
+ rom_path = get_roms_structure(p_slug)
if _rom_exists(p_slug, new_name):
- log.info(f"Can't rename {old_name} to {new_name}. {new_name} already exists")
- raise HTTPException(status_code=500, detail=f"Can't rename: {new_name} already exists.")
+ raise RomAlreadyExistsException(new_name)
os.rename(f"{rom_path}/{old_name}", f"{rom_path}/{new_name}")
def remove_rom(p_slug: str, file_name: str) -> None:
- rom_path = _get_roms_structure(p_slug)
+ rom_path = get_roms_structure(p_slug)
try:
try:
os.remove(f"{rom_path}/{file_name}")
except IsADirectoryError:
shutil.rmtree(f"{rom_path}/{file_name}")
except FileNotFoundError:
- log.error(f"{rom_path}/{file_name} not found in filesystem")
-
-
-def _cover_exists(p_slug: str, file_name: str, size: str) -> bool:
- """Check if rom cover exists in filesystem
-
- Args:
- p_slug: short name of the platform
- file_name: name of rom file
- size: size of the cover -> big as 'l' | small as 's'
- Returns
- True if cover exists in filesystem else False
- """
- logo_path: str = f"{RESOURCES_BASE_PATH}/{p_slug}/{file_name}_{size}.png"
- return True if os.path.exists(logo_path) else False
-
-
-def _store_cover(p_slug: str, file_name: str, url_cover: str, size: str) -> None:
- """Store roms resources in filesystem
-
- Args:
- p_slug: short name of the platform
- file_name: name of rom file
- url_cover: url to get the cover
- size: size of the cover -> big as 'l' | small as 's'
- """
- cover_file: str = f"{file_name}_{size}.png"
- cover_path: str = f"{RESOURCES_BASE_PATH}/{p_slug}/"
- sizes: dict = {'l': 'big', 's': 'small'}
- res = requests.get(url_cover.replace('t_thumb', f't_cover_{sizes[size]}'), stream=True)
- if res.status_code == 200:
- Path(cover_path).mkdir(parents=True, exist_ok=True)
- with open(f"{cover_path}/{cover_file}", 'wb') as f:
- shutil.copyfileobj(res.raw, f)
- log.info(f"{file_name} {sizes[size]} cover downloaded successfully!")
- else:
- log.error(f"{file_name} {sizes[size]} cover couldn't be downloaded")
-
-
-def _get_cover_path(p_slug: str, file_name: str, size: str) -> str:
- """Returns rom cover filesystem path adapted to frontend folder structure
-
- Args:
- p_slug: short name of the platform
- file_name: name of rom file
- size: size of the cover -> big as 'l' | small as 's'
- """
- return f"{RESOURCES_BASE_PATH}/{p_slug}/{file_name}_{size}.png"
-
-
-def get_cover_details(overwrite: bool, p_slug: str, file_name: str, url_cover: str) -> tuple:
- path_cover_s: str = DEFAULT_PATH_COVER_S
- path_cover_l: str = DEFAULT_PATH_COVER_L
- has_cover: int = 0
- if (overwrite or not _cover_exists(p_slug, file_name, 's')) and url_cover:
- _store_cover(p_slug, file_name, url_cover, 's')
- if _cover_exists(p_slug, file_name, 's'):
- path_cover_s = _get_cover_path(p_slug, file_name, 's')
-
- if (overwrite or not _cover_exists(p_slug, file_name, 'l')) and url_cover:
- _store_cover(p_slug, file_name, url_cover, 'l')
- if _cover_exists(p_slug, file_name, 'l'):
- path_cover_l = _get_cover_path(p_slug, file_name, 'l')
- has_cover = 1
- return path_cover_s, path_cover_l, has_cover
+ raise RomNotFoundError(file_name, p_slug)
diff --git a/docker/config.example.yml b/examples/config.example.yml
similarity index 71%
rename from docker/config.example.yml
rename to examples/config.example.yml
index 10f5ce6b2..47202b23b 100644
--- a/docker/config.example.yml
+++ b/examples/config.example.yml
@@ -28,4 +28,11 @@ exclude:
- 'data.xml'
# Exclude all files with certain extensions to be scanned from multi file roms
extensions:
- - 'txt'
\ No newline at end of file
+ - 'txt'
+
+# Asociate different platform names to your current file system platform names
+system:
+ platforms:
+ # [your custom platform folder name]: [RomM platform name]
+ gc: 'ngc' # In this example if you have a 'gc' folder, RomM will treat it like the 'ngc' folder
+ psx: 'ps' # In this example if you have a 'psx' folder, RomM will treat it like the 'ps' folder
diff --git a/docker/docker-compose.example.yml b/examples/docker-compose.example.yml
similarity index 100%
rename from docker/docker-compose.example.yml
rename to examples/docker-compose.example.yml
diff --git a/frontend/.env b/frontend/.env
index 481f0e387..0e1c4c7e4 100644
--- a/frontend/.env
+++ b/frontend/.env
@@ -1 +1 @@
-VITE_ROMM_VERSION=1.7.1
\ No newline at end of file
+VITE_ROMM_VERSION=1.8
\ No newline at end of file
diff --git a/frontend/assets/isotipo.svg b/frontend/assets/isotipo.svg
new file mode 100644
index 000000000..d39dea315
--- /dev/null
+++ b/frontend/assets/isotipo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/assets/logotipo.svg b/frontend/assets/logotipo.svg
new file mode 100644
index 000000000..bf99469bc
--- /dev/null
+++ b/frontend/assets/logotipo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/assets/old/romm.ico b/frontend/assets/old/romm.ico
deleted file mode 100644
index 73eb89e90..000000000
Binary files a/frontend/assets/old/romm.ico and /dev/null differ
diff --git a/frontend/assets/old/romm.png b/frontend/assets/old/romm.png
deleted file mode 100644
index 5583da5c6..000000000
Binary files a/frontend/assets/old/romm.png and /dev/null differ
diff --git a/frontend/assets/old/romm_base.png b/frontend/assets/old/romm_base.png
deleted file mode 100644
index b8553352d..000000000
Binary files a/frontend/assets/old/romm_base.png and /dev/null differ
diff --git a/frontend/assets/platforms/saturn.ico b/frontend/assets/platforms/saturn.ico
new file mode 100644
index 000000000..38ed68c65
Binary files /dev/null and b/frontend/assets/platforms/saturn.ico differ
diff --git a/frontend/assets/platforms/sms.ico b/frontend/assets/platforms/sms.ico
new file mode 100644
index 000000000..a64f3177c
Binary files /dev/null and b/frontend/assets/platforms/sms.ico differ
diff --git a/frontend/assets/romm.svg b/frontend/assets/romm.svg
deleted file mode 100644
index cff16aa75..000000000
--- a/frontend/assets/romm.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/frontend/index.html b/frontend/index.html
index 08739aa03..3aede4431 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -3,7 +3,7 @@
-
+
RomM
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index fbe4d17fb..103c6f79c 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -1,44 +1,1768 @@
{
"name": "romm",
- "version": "1.7.1",
+ "version": "1.8",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "romm",
- "version": "1.7.1",
+ "version": "1.8",
+ "dependencies": {
+ "@mdi/font": "7.0.96",
+ "axios": "^1.3.4",
+ "core-js": "^3.8.3",
+ "file-saver": "^2.0.5",
+ "jszip": "^3.10.1",
+ "mitt": "^3.0.0",
+ "pinia": "^2.0.35",
+ "roboto-fontface": "*",
+ "vue": "^3.2.13",
+ "vue-router": "^4.0.0",
+ "vuetify": "^3.1.15",
+ "webfontloader": "^1.0.0"
+ },
+ "devDependencies": {
+ "@types/file-saver": "^2.0.5",
+ "@vitejs/plugin-vue": "^3.0.3",
+ "eslint": "^8.22.0",
+ "eslint-plugin-vue": "^9.3.0",
+ "sass": "^1.55.0",
+ "vite": "^3.1.9",
+ "vite-plugin-pwa": "^0.14.7",
+ "vite-plugin-rewrite-all": "^1.0.1",
+ "vite-plugin-vuetify": "^1.0.0-alpha.12"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
+ "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.21.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz",
+ "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.21.4",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz",
+ "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.21.4",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz",
+ "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.21.4",
+ "@babel/generator": "^7.21.4",
+ "@babel/helper-compilation-targets": "^7.21.4",
+ "@babel/helper-module-transforms": "^7.21.2",
+ "@babel/helpers": "^7.21.0",
+ "@babel/parser": "^7.21.4",
+ "@babel/template": "^7.20.7",
+ "@babel/traverse": "^7.21.4",
+ "@babel/types": "^7.21.4",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.2",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "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/@babel/generator": {
+ "version": "7.21.4",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz",
+ "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.21.4",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-explode-assignable-expression": "^7.18.6",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.21.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz",
+ "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.21.4",
+ "@babel/helper-validator-option": "^7.21.0",
+ "browserslist": "^4.21.3",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
+ "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,
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/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/@babel/helper-compilation-targets/node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
+ "version": "7.21.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.4.tgz",
+ "integrity": "sha512-46QrX2CQlaFRF4TkwfTt6nJD7IHq8539cCL7SDpqWSDeJKY1xylKKY5F/33mJhLZ3mFvKv2gGrVS6NkyF6qs+Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-environment-visitor": "^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.20.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0",
+ "@babel/helper-split-export-declaration": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-regexp-features-plugin": {
+ "version": "7.21.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.4.tgz",
+ "integrity": "sha512-M00OuhU+0GyZ5iBBN9czjugzWrEq2vDpf/zCYHxxf93ul/Q5rv+a5h+/+0WnI1AebHNVtl5bFV0qsJoH23DbfA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "regexpu-core": "^5.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@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"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0-0"
+ }
+ },
+ "node_modules/@babel/helper-define-polyfill-provider/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/@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,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "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.20.7",
+ "@babel/types": "^7.21.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "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.21.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.21.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz",
+ "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.21.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "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.20.2",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@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"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "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"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-replace-supers": {
+ "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.20.7",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@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.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.20.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "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.20.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@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,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@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,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "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.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.20.5",
+ "@babel/types": "^7.20.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "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.20.7",
+ "@babel/traverse": "^7.21.0",
+ "@babel/types": "^7.21.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/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,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/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,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/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,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/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
+ },
+ "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/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,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/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,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.21.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz",
+ "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==",
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
+ "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.20.2",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0",
+ "@babel/plugin-proposal-optional-chaining": "^7.20.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.13.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-async-generator-functions": {
+ "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.20.2",
+ "@babel/helper-remap-async-to-generator": "^7.18.9",
+ "@babel/plugin-syntax-async-generators": "^7.8.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-class-static-block": {
+ "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.21.0",
+ "@babel/helper-plugin-utils": "^7.20.2",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.12.0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-json-strings": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-logical-assignment-operators": {
+ "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.20.2",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-object-rest-spread": {
+ "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.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.20.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-optional-chaining": {
+ "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.20.2",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-private-property-in-object": {
+ "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.21.0",
+ "@babel/helper-plugin-utils": "^7.20.2",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-assertions": {
+ "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.19.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-arrow-functions": {
+ "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.20.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-async-to-generator": {
+ "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.20.2",
+ "@babel/helper-remap-async-to-generator": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoping": {
+ "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.20.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-classes": {
+ "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.20.7",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.21.0",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@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"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-classes/node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/plugin-transform-computed-properties": {
+ "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.20.2",
+ "@babel/template": "^7.20.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-destructuring": {
+ "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.20.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-for-of": {
+ "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.20.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-amd": {
+ "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.20.11",
+ "@babel/helper-plugin-utils": "^7.20.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "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.21.2",
+ "@babel/helper-plugin-utils": "^7.20.2",
+ "@babel/helper-simple-access": "^7.20.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-systemjs": {
+ "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.20.11",
+ "@babel/helper-plugin-utils": "^7.20.2",
+ "@babel/helper-validator-identifier": "^7.19.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
+ "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.20.5",
+ "@babel/helper-plugin-utils": "^7.20.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-replace-supers": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-parameters": {
+ "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.20.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-regenerator": {
+ "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.20.2",
+ "regenerator-transform": "^0.15.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-spread": {
+ "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.20.2",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@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,
"dependencies": {
- "@mdi/font": "7.0.96",
- "axios": "^1.3.4",
- "core-js": "^3.8.3",
- "file-saver": "^2.0.5",
- "jszip": "^3.10.1",
- "mitt": "^3.0.0",
- "roboto-fontface": "*",
- "vue": "^3.2.13",
- "vue-router": "^4.0.0",
- "vuetify": "^3.0.0",
- "webfontloader": "^1.0.0"
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
},
- "devDependencies": {
- "@types/file-saver": "^2.0.5",
- "@vitejs/plugin-vue": "^3.0.3",
- "eslint": "^8.22.0",
- "eslint-plugin-vue": "^9.3.0",
- "sass": "^1.55.0",
- "vite": "^3.1.9",
- "vite-plugin-vuetify": "^1.0.0-alpha.12"
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/parser": {
- "version": "7.21.2",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz",
- "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==",
+ "node_modules/@babel/preset-env": {
+ "version": "7.21.4",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.21.4.tgz",
+ "integrity": "sha512-2W57zHs2yDLm6GD5ZpvNn71lZ0B/iypSdIeq25OurDKji6AdzV07qp4s3n1/x5BqtiGaTrPN3nerlSCaC5qNTw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.21.4",
+ "@babel/helper-compilation-targets": "^7.21.4",
+ "@babel/helper-plugin-utils": "^7.20.2",
+ "@babel/helper-validator-option": "^7.21.0",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.20.7",
+ "@babel/plugin-proposal-async-generator-functions": "^7.20.7",
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
+ "@babel/plugin-proposal-class-static-block": "^7.21.0",
+ "@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.20.7",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
+ "@babel/plugin-proposal-numeric-separator": "^7.18.6",
+ "@babel/plugin-proposal-object-rest-spread": "^7.20.7",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.18.6",
+ "@babel/plugin-proposal-optional-chaining": "^7.21.0",
+ "@babel/plugin-proposal-private-methods": "^7.18.6",
+ "@babel/plugin-proposal-private-property-in-object": "^7.21.0",
+ "@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.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",
+ "@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.20.7",
+ "@babel/plugin-transform-async-to-generator": "^7.20.7",
+ "@babel/plugin-transform-block-scoped-functions": "^7.18.6",
+ "@babel/plugin-transform-block-scoping": "^7.21.0",
+ "@babel/plugin-transform-classes": "^7.21.0",
+ "@babel/plugin-transform-computed-properties": "^7.20.7",
+ "@babel/plugin-transform-destructuring": "^7.21.3",
+ "@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.21.0",
+ "@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.20.11",
+ "@babel/plugin-transform-modules-commonjs": "^7.21.2",
+ "@babel/plugin-transform-modules-systemjs": "^7.20.11",
+ "@babel/plugin-transform-modules-umd": "^7.18.6",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.20.5",
+ "@babel/plugin-transform-new-target": "^7.18.6",
+ "@babel/plugin-transform-object-super": "^7.18.6",
+ "@babel/plugin-transform-parameters": "^7.21.3",
+ "@babel/plugin-transform-property-literals": "^7.18.6",
+ "@babel/plugin-transform-regenerator": "^7.20.5",
+ "@babel/plugin-transform-reserved-words": "^7.18.6",
+ "@babel/plugin-transform-shorthand-properties": "^7.18.6",
+ "@babel/plugin-transform-spread": "^7.20.7",
+ "@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.21.4",
+ "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": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-env/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": {
- "parser": "bin/babel-parser.js"
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@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,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+ "@babel/plugin-transform-dotall-regex": "^7.4.4",
+ "@babel/types": "^7.4.4",
+ "esutils": "^2.0.2"
+ },
+ "peerDependencies": {
+ "@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.21.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz",
+ "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==",
+ "dev": true,
+ "dependencies": {
+ "regenerator-runtime": "^0.13.11"
},
"engines": {
- "node": ">=6.0.0"
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "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.20.7",
+ "@babel/types": "^7.20.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.21.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz",
+ "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.21.4",
+ "@babel/generator": "^7.21.4",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@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.21.4",
+ "@babel/types": "^7.21.4",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.21.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz",
+ "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.19.4",
+ "@babel/helper-validator-identifier": "^7.19.1",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
}
},
"node_modules/@esbuild/android-arm": {
@@ -136,6 +1860,70 @@
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
"dev": true
},
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+ "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+ "devOptional": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@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==",
+ "devOptional": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@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==",
+ "devOptional": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz",
+ "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==",
+ "devOptional": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+ "devOptional": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
+ "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
+ "devOptional": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ }
+ },
+ "node_modules/@jridgewell/trace-mapping/node_modules/@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==",
+ "devOptional": true
+ },
"node_modules/@mdi/font": {
"version": "7.0.96",
"resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.0.96.tgz",
@@ -176,12 +1964,207 @@
"node": ">= 8"
}
},
+ "node_modules/@rollup/plugin-babel": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
+ "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.10.4",
+ "@rollup/pluginutils": "^3.1.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0",
+ "@types/babel__core": "^7.1.9",
+ "rollup": "^1.20.0||^2.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/babel__core": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/plugin-babel/node_modules/@rollup/pluginutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
+ "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "0.0.39",
+ "estree-walker": "^1.0.1",
+ "picomatch": "^2.2.2"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0"
+ }
+ },
+ "node_modules/@rollup/plugin-babel/node_modules/@types/estree": {
+ "version": "0.0.39",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+ "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+ "dev": true
+ },
+ "node_modules/@rollup/plugin-babel/node_modules/estree-walker": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
+ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
+ "dev": true
+ },
+ "node_modules/@rollup/plugin-node-resolve": {
+ "version": "11.2.1",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz",
+ "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==",
+ "dev": true,
+ "dependencies": {
+ "@rollup/pluginutils": "^3.1.0",
+ "@types/resolve": "1.17.1",
+ "builtin-modules": "^3.1.0",
+ "deepmerge": "^4.2.2",
+ "is-module": "^1.0.0",
+ "resolve": "^1.19.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0"
+ }
+ },
+ "node_modules/@rollup/plugin-node-resolve/node_modules/@rollup/pluginutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
+ "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "0.0.39",
+ "estree-walker": "^1.0.1",
+ "picomatch": "^2.2.2"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0"
+ }
+ },
+ "node_modules/@rollup/plugin-node-resolve/node_modules/@types/estree": {
+ "version": "0.0.39",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+ "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+ "dev": true
+ },
+ "node_modules/@rollup/plugin-node-resolve/node_modules/estree-walker": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
+ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
+ "dev": true
+ },
+ "node_modules/@rollup/plugin-replace": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.2.tgz",
+ "integrity": "sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==",
+ "dev": true,
+ "dependencies": {
+ "@rollup/pluginutils": "^5.0.1",
+ "magic-string": "^0.27.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0||^3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/plugin-replace/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/@rollup/pluginutils": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz",
+ "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-walker": "^2.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0||^3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@surma/rollup-plugin-off-main-thread": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
+ "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==",
+ "dev": true,
+ "dependencies": {
+ "ejs": "^3.1.6",
+ "json5": "^2.2.0",
+ "magic-string": "^0.25.0",
+ "string.prototype.matchall": "^4.0.6"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
+ "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==",
+ "dev": true
+ },
"node_modules/@types/file-saver": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.5.tgz",
"integrity": "sha512-zv9kNf3keYegP5oThGLaPk8E081DFDuwfqjtiTzm6PoxChdJ1raSuADf2YGCVIyrSynLrgc8JWv296s7Q7pQSQ==",
"dev": true
},
+ "node_modules/@types/node": {
+ "version": "18.15.11",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz",
+ "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==",
+ "devOptional": true
+ },
+ "node_modules/@types/resolve": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
+ "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz",
+ "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==",
+ "dev": true
+ },
"node_modules/@vitejs/plugin-vue": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-3.2.0.tgz",
@@ -320,7 +2303,7 @@
"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,
+ "devOptional": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -396,19 +2379,107 @@
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
},
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+ "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "is-array-buffer": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
+ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==",
+ "dev": true
+ },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
- "node_modules/axios": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
- "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
+ "node_modules/at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
+ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/axios": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
+ "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
+ "dependencies": {
+ "follow-redirects": "^1.15.0",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/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,
+ "dependencies": {
+ "@babel/compat-data": "^7.17.7",
+ "@babel/helper-define-polyfill-provider": "^0.3.3",
+ "semver": "^6.1.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs2/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/babel-plugin-polyfill-corejs3": {
+ "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.3",
+ "core-js-compat": "^3.25.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/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,
"dependencies": {
- "follow-redirects": "^1.15.0",
- "form-data": "^4.0.0",
- "proxy-from-env": "^1.1.0"
+ "@babel/helper-define-polyfill-provider": "^0.3.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
"node_modules/balanced-match": {
@@ -454,6 +2525,65 @@
"node": ">=8"
}
},
+ "node_modules/browserslist": {
+ "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": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ }
+ ],
+ "dependencies": {
+ "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"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/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==",
+ "devOptional": true
+ },
+ "node_modules/builtin-modules": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
+ "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/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,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -463,6 +2593,26 @@
"node": ">=6"
}
},
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001480",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001480.tgz",
+ "integrity": "sha512-q7cpoPPvZYgtyC4VaBSN0Bt+PJ4c4EYRf0DrduInOz2SkFpHD5p3LnvEpqBp7UnJn+8x1Ogl1s38saUxe+ihQQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -547,6 +2697,21 @@
"node": ">= 0.8"
}
},
+ "node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "devOptional": true
+ },
+ "node_modules/common-tags": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
+ "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
@@ -559,6 +2724,21 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
},
+ "node_modules/connect-history-api-fallback": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
+ "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
+ "dev": true
+ },
"node_modules/core-js": {
"version": "3.29.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.29.0.tgz",
@@ -569,6 +2749,19 @@
"url": "https://opencollective.com/core-js"
}
},
+ "node_modules/core-js-compat": {
+ "version": "3.30.1",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.30.1.tgz",
+ "integrity": "sha512-d690npR7MC6P0gq4npTl5n2VQeNAmUrJ90n+MHiKS7W2+xno4o3F5GDEuylSdi6EJ3VssibSGXOa1r3YXD3Mhw==",
+ "dev": true,
+ "dependencies": {
+ "browserslist": "^4.21.5"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -588,6 +2781,15 @@
"node": ">= 8"
}
},
+ "node_modules/crypto-random-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
+ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@@ -628,6 +2830,31 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
+ "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
+ "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/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -648,6 +2875,106 @@
"node": ">=6.0.0"
}
},
+ "node_modules/ejs": {
+ "version": "3.1.9",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz",
+ "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==",
+ "dev": true,
+ "dependencies": {
+ "jake": "^10.8.5"
+ },
+ "bin": {
+ "ejs": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.365",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.365.tgz",
+ "integrity": "sha512-FRHZO+1tUNO4TOPXmlxetkoaIY8uwHzd1kKopK/Gx2SKn1L47wJXWD44wxP5CGRyyP98z/c8e1eBzJrgPeiBOg==",
+ "dev": true
+ },
+ "node_modules/es-abstract": {
+ "version": "1.21.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz",
+ "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "es-set-tostringtag": "^2.0.1",
+ "es-to-primitive": "^1.2.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.2.0",
+ "get-symbol-description": "^1.0.0",
+ "globalthis": "^1.0.3",
+ "gopd": "^1.0.1",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.5",
+ "is-array-buffer": "^3.0.2",
+ "is-callable": "^1.2.7",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-typed-array": "^1.1.10",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.3",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.4.3",
+ "safe-regex-test": "^1.0.0",
+ "string.prototype.trim": "^1.2.7",
+ "string.prototype.trimend": "^1.0.6",
+ "string.prototype.trimstart": "^1.0.6",
+ "typed-array-length": "^1.0.4",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
+ "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.3",
+ "has": "^1.0.3",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/esbuild": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
@@ -985,6 +3312,15 @@
"node": ">=12"
}
},
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -1194,6 +3530,34 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
+ "node_modules/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,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -1232,6 +3596,36 @@
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
},
+ "node_modules/filelist": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
+ "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
+ "dev": true,
+ "dependencies": {
+ "minimatch": "^5.0.1"
+ }
+ },
+ "node_modules/filelist/node_modules/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,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/filelist/node_modules/minimatch": {
+ "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"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -1315,6 +3709,15 @@
}
}
},
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
@@ -1328,6 +3731,21 @@
"node": ">= 6"
}
},
+ "node_modules/fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "dependencies": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -1353,6 +3771,78 @@
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"devOptional": true
},
+ "node_modules/function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "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",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-own-enumerable-property-symbols": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
+ "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==",
+ "dev": true
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -1400,6 +3890,39 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/globalthis": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+ "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "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/grapheme-splitter": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
@@ -1418,6 +3941,15 @@
"node": ">= 0.4.0"
}
},
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -1427,6 +3959,63 @@
"node": ">=8"
}
},
+ "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-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "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",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/idb": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
+ "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==",
+ "dev": true
+ },
"node_modules/ignore": {
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
@@ -1487,6 +4076,46 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
+ "node_modules/internal-slot": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
+ "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+ "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.0",
+ "is-typed-array": "^1.1.10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@@ -1499,6 +4128,34 @@
"node": ">=8"
}
},
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-core-module": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
@@ -1511,6 +4168,21 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -1532,6 +4204,24 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
+ "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
+ "dev": true
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -1541,6 +4231,30 @@
"node": ">=0.12.0"
}
},
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/is-path-inside": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
@@ -1550,6 +4264,116 @@
"node": ">=8"
}
},
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-regexp": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
+ "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz",
+ "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -1561,6 +4385,38 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
+ "node_modules/jake": {
+ "version": "10.8.5",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
+ "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
+ "dev": true,
+ "dependencies": {
+ "async": "^3.2.3",
+ "chalk": "^4.0.2",
+ "filelist": "^1.0.1",
+ "minimatch": "^3.0.4"
+ },
+ "bin": {
+ "jake": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
+ "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^7.0.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
"node_modules/js-sdsl": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
@@ -1571,6 +4427,12 @@
"url": "https://opencollective.com/js-sdsl"
}
},
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
@@ -1583,6 +4445,24 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/json-schema": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+ "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
+ "dev": true
+ },
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -1595,6 +4475,39 @@
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true
},
+ "node_modules/json5": {
+ "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"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsonpointer": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz",
+ "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/jszip": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
@@ -1606,6 +4519,15 @@
"setimmediate": "^1.0.5"
}
},
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@@ -1648,12 +4570,24 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
+ "node_modules/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
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
+ "node_modules/lodash.sortby": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
+ "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==",
+ "dev": true
+ },
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@@ -1698,6 +4632,34 @@
"semver": "bin/semver.js"
}
},
+ "node_modules/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
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -1757,6 +4719,12 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
+ "node_modules/node-releases": {
+ "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/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -1778,6 +4746,42 @@
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
+ "node_modules/object-inspect": {
+ "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/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -1910,6 +4914,56 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/pinia": {
+ "version": "2.0.35",
+ "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.35.tgz",
+ "integrity": "sha512-P1IKKQWhxGXiiZ3atOaNI75bYlFUbRxtJdhPLX059Z7+b9Z04rnTZdSY8Aph1LA+/4QEMAYHsTQ638Wfe+6K5g==",
+ "dependencies": {
+ "@vue/devtools-api": "^6.5.0",
+ "vue-demi": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/posva"
+ },
+ "peerDependencies": {
+ "@vue/composition-api": "^1.4.0",
+ "typescript": ">=4.4.4",
+ "vue": "^2.6.14 || ^3.2.0"
+ },
+ "peerDependenciesMeta": {
+ "@vue/composition-api": {
+ "optional": true
+ },
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/pinia/node_modules/vue-demi": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.0.tgz",
+ "integrity": "sha512-gt58r2ogsNQeVoQ3EhoUAvUsH9xviydl0dWJj7dabBC/2L4uBId7ujtCwDRD0JhkGsV1i0CtfLAeyYKBht9oWg==",
+ "hasInstallScript": true,
+ "bin": {
+ "vue-demi-fix": "bin/vue-demi-fix.js",
+ "vue-demi-switch": "bin/vue-demi-switch.js"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "@vue/composition-api": "^1.0.0-rc.1",
+ "vue": "^3.0.0-0 || ^2.6.0"
+ },
+ "peerDependenciesMeta": {
+ "@vue/composition-api": {
+ "optional": true
+ }
+ }
+ },
"node_modules/pkg-dir": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
@@ -2019,6 +5073,18 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/pretty-bytes": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.0.tgz",
+ "integrity": "sha512-Rk753HI8f4uivXi4ZCIYdhmG1V+WKzvRMg/X+M42a6t7D07RcmopXJMDNk6N++7Bl75URRGsb40ruvg7Hcp2wQ==",
+ "dev": true,
+ "engines": {
+ "node": "^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -2058,6 +5124,15 @@
}
]
},
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
"node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
@@ -2084,6 +5159,56 @@
"node": ">=8.10.0"
}
},
+ "node_modules/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
+ },
+ "node_modules/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,
+ "dependencies": {
+ "regenerate": "^1.4.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "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.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"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
+ "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/regexpp": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
@@ -2096,6 +5221,53 @@
"url": "https://github.com/sponsors/mysticatea"
}
},
+ "node_modules/regexpu-core": {
+ "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",
+ "regjsparser": "^0.9.1",
+ "unicode-match-property-ecmascript": "^2.0.0",
+ "unicode-match-property-value-ecmascript": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regjsparser": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz",
+ "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==",
+ "dev": true,
+ "dependencies": {
+ "jsesc": "~0.5.0"
+ },
+ "bin": {
+ "regjsparser": "bin/parser"
+ }
+ },
+ "node_modules/regjsparser/node_modules/jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/resolve": {
"version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
@@ -2167,6 +5339,22 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/rollup-plugin-terser": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz",
+ "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==",
+ "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "jest-worker": "^26.2.1",
+ "serialize-javascript": "^4.0.0",
+ "terser": "^5.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^2.0.0"
+ }
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -2195,6 +5383,20 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
+ "node_modules/safe-regex-test": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
+ "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.3",
+ "is-regex": "^1.1.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/sass": {
"version": "1.58.3",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.58.3.tgz",
@@ -2227,6 +5429,15 @@
"node": ">=10"
}
},
+ "node_modules/serialize-javascript": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
+ "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
"node_modules/setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
@@ -2253,6 +5464,20 @@
"node": ">=8"
}
},
+ "node_modules/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,
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -2269,6 +5494,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/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==",
+ "devOptional": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
"node_modules/sourcemap-codec": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
@@ -2283,6 +5518,84 @@
"safe-buffer": "~5.1.0"
}
},
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
+ "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "get-intrinsic": "^1.1.3",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.3",
+ "regexp.prototype.flags": "^1.4.3",
+ "side-channel": "^1.0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
+ "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
+ "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz",
+ "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/stringify-object": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz",
+ "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==",
+ "dev": true,
+ "dependencies": {
+ "get-own-enumerable-property-symbols": "^3.0.0",
+ "is-obj": "^1.0.1",
+ "is-regexp": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@@ -2295,6 +5608,15 @@
"node": ">=8"
}
},
+ "node_modules/strip-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz",
+ "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -2331,12 +5653,78 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/temp-dir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
+ "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tempy": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz",
+ "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==",
+ "dev": true,
+ "dependencies": {
+ "is-stream": "^2.0.0",
+ "temp-dir": "^2.0.0",
+ "type-fest": "^0.16.0",
+ "unique-string": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/tempy/node_modules/type-fest": {
+ "version": "0.16.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz",
+ "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.16.9",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.9.tgz",
+ "integrity": "sha512-HPa/FdTB9XGI2H1/keLFZHxl6WNvAI4YalHGtDQTlMnJcoqSab1UwL4l1hGEhs6/GmLHBZIg/YgB++jcbzoOEg==",
+ "devOptional": 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/text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
"dev": true
},
+ "node_modules/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,
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -2349,6 +5737,15 @@
"node": ">=8.0"
}
},
+ "node_modules/tr46": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
+ "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -2373,6 +5770,96 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/typed-array-length": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
+ "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "is-typed-array": "^1.1.9"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/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,
+ "dependencies": {
+ "unicode-canonical-property-names-ecmascript": "^2.0.0",
+ "unicode-property-aliases-ecmascript": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-value-ecmascript": {
+ "version": "2.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"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unique-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
+ "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
+ "dev": true,
+ "dependencies": {
+ "crypto-random-string": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
"node_modules/upath": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz",
@@ -2383,6 +5870,36 @@
"yarn": "*"
}
},
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
+ "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -2446,6 +5963,60 @@
}
}
},
+ "node_modules/vite-plugin-pwa": {
+ "version": "0.14.7",
+ "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.14.7.tgz",
+ "integrity": "sha512-dNJaf0fYOWncmjxv9HiSa2xrSjipjff7IkYE5oIUJ2x5HKu3cXgA8LRgzOwTc5MhwyFYRSU0xyN0Phbx3NsQYw==",
+ "dev": true,
+ "dependencies": {
+ "@rollup/plugin-replace": "^5.0.1",
+ "debug": "^4.3.4",
+ "fast-glob": "^3.2.12",
+ "pretty-bytes": "^6.0.0",
+ "rollup": "^3.7.2",
+ "workbox-build": "^6.5.4",
+ "workbox-window": "^6.5.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "vite": "^3.1.0 || ^4.0.0",
+ "workbox-build": "^6.5.4",
+ "workbox-window": "^6.5.4"
+ }
+ },
+ "node_modules/vite-plugin-pwa/node_modules/rollup": {
+ "version": "3.20.4",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.4.tgz",
+ "integrity": "sha512-n7J4tuctZXUErM9Uc916httwqmTc63zzCr2+TLCiSCpfO/Xuk3g/marGN1IlRJZi+QF3XMYx75PxXRfZDVgaRw==",
+ "dev": true,
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=14.18.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/vite-plugin-rewrite-all": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/vite-plugin-rewrite-all/-/vite-plugin-rewrite-all-1.0.1.tgz",
+ "integrity": "sha512-W0DAchC8ynuQH0lYLIu5/5+JGfYlUTRD8GGNtHFXRJX4FzzB9MajtqHBp26zq/ly9sDt5BqrfdT08rv3RbB0LQ==",
+ "dev": true,
+ "dependencies": {
+ "connect-history-api-fallback": "^1.6.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^2.0.0 || ^3.0.0 || ^4.0.0"
+ }
+ },
"node_modules/vite-plugin-vuetify": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/vite-plugin-vuetify/-/vite-plugin-vuetify-1.0.2.tgz",
@@ -2515,9 +6086,9 @@
}
},
"node_modules/vuetify": {
- "version": "3.1.8",
- "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.1.8.tgz",
- "integrity": "sha512-yODCnRxERSvcBwC6qPiySVhmZzNZ2Yme6b2lNLY1G8W/hbipAtbTCFVGB4ZY/qY7D7JNQBxzgVfZme7bDY9ZrQ==",
+ "version": "3.1.15",
+ "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.1.15.tgz",
+ "integrity": "sha512-uxB4UCrP+hFyJaoSsVObAGBRD73qq5ga7HULepzGoMeUWap2H99mcqmMdN/a/Yp4ODK3gT8EcUeph3EgEcsArQ==",
"engines": {
"node": "^12.20 || >=14.13"
},
@@ -2548,6 +6119,23 @@
"resolved": "https://registry.npmjs.org/webfontloader/-/webfontloader-1.6.28.tgz",
"integrity": "sha512-Egb0oFEga6f+nSgasH3E0M405Pzn6y3/9tOVanv/DLfa1YBIgcv90L18YyWnvXkRbIM17v5Kv6IT2N6g1x5tvQ=="
},
+ "node_modules/webidl-conversions": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+ "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
+ "dev": true
+ },
+ "node_modules/whatwg-url": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
+ "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
+ "dev": true,
+ "dependencies": {
+ "lodash.sortby": "^4.7.0",
+ "tr46": "^1.0.1",
+ "webidl-conversions": "^4.0.2"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -2563,6 +6151,42 @@
"node": ">= 8"
}
},
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz",
+ "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@@ -2572,6 +6196,312 @@
"node": ">=0.10.0"
}
},
+ "node_modules/workbox-background-sync": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.5.4.tgz",
+ "integrity": "sha512-0r4INQZMyPky/lj4Ou98qxcThrETucOde+7mRGJl13MPJugQNKeZQOdIJe/1AchOP23cTqHcN/YVpD6r8E6I8g==",
+ "dev": true,
+ "dependencies": {
+ "idb": "^7.0.1",
+ "workbox-core": "6.5.4"
+ }
+ },
+ "node_modules/workbox-broadcast-update": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.4.tgz",
+ "integrity": "sha512-I/lBERoH1u3zyBosnpPEtcAVe5lwykx9Yg1k6f8/BGEPGaMMgZrwVrqL1uA9QZ1NGGFoyE6t9i7lBjOlDhFEEw==",
+ "dev": true,
+ "dependencies": {
+ "workbox-core": "6.5.4"
+ }
+ },
+ "node_modules/workbox-build": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.4.tgz",
+ "integrity": "sha512-kgRevLXEYvUW9WS4XoziYqZ8Q9j/2ziJYEtTrjdz5/L/cTUa2XfyMP2i7c3p34lgqJ03+mTiz13SdFef2POwbA==",
+ "dev": true,
+ "dependencies": {
+ "@apideck/better-ajv-errors": "^0.3.1",
+ "@babel/core": "^7.11.1",
+ "@babel/preset-env": "^7.11.0",
+ "@babel/runtime": "^7.11.2",
+ "@rollup/plugin-babel": "^5.2.0",
+ "@rollup/plugin-node-resolve": "^11.2.1",
+ "@rollup/plugin-replace": "^2.4.1",
+ "@surma/rollup-plugin-off-main-thread": "^2.2.3",
+ "ajv": "^8.6.0",
+ "common-tags": "^1.8.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "fs-extra": "^9.0.1",
+ "glob": "^7.1.6",
+ "lodash": "^4.17.20",
+ "pretty-bytes": "^5.3.0",
+ "rollup": "^2.43.1",
+ "rollup-plugin-terser": "^7.0.0",
+ "source-map": "^0.8.0-beta.0",
+ "stringify-object": "^3.3.0",
+ "strip-comments": "^2.0.1",
+ "tempy": "^0.6.0",
+ "upath": "^1.2.0",
+ "workbox-background-sync": "6.5.4",
+ "workbox-broadcast-update": "6.5.4",
+ "workbox-cacheable-response": "6.5.4",
+ "workbox-core": "6.5.4",
+ "workbox-expiration": "6.5.4",
+ "workbox-google-analytics": "6.5.4",
+ "workbox-navigation-preload": "6.5.4",
+ "workbox-precaching": "6.5.4",
+ "workbox-range-requests": "6.5.4",
+ "workbox-recipes": "6.5.4",
+ "workbox-routing": "6.5.4",
+ "workbox-strategies": "6.5.4",
+ "workbox-streams": "6.5.4",
+ "workbox-sw": "6.5.4",
+ "workbox-window": "6.5.4"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz",
+ "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==",
+ "dev": true,
+ "dependencies": {
+ "json-schema": "^0.4.0",
+ "jsonpointer": "^5.0.0",
+ "leven": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "ajv": ">=8"
+ }
+ },
+ "node_modules/workbox-build/node_modules/@rollup/plugin-replace": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz",
+ "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==",
+ "dev": true,
+ "dependencies": {
+ "@rollup/pluginutils": "^3.1.0",
+ "magic-string": "^0.25.7"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0 || ^2.0.0"
+ }
+ },
+ "node_modules/workbox-build/node_modules/@rollup/pluginutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
+ "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "0.0.39",
+ "estree-walker": "^1.0.1",
+ "picomatch": "^2.2.2"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0"
+ }
+ },
+ "node_modules/workbox-build/node_modules/@types/estree": {
+ "version": "0.0.39",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+ "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+ "dev": true
+ },
+ "node_modules/workbox-build/node_modules/ajv": {
+ "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",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/workbox-build/node_modules/estree-walker": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
+ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
+ "dev": true
+ },
+ "node_modules/workbox-build/node_modules/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
+ },
+ "node_modules/workbox-build/node_modules/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,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/workbox-build/node_modules/source-map": {
+ "version": "0.8.0-beta.0",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz",
+ "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==",
+ "dev": true,
+ "dependencies": {
+ "whatwg-url": "^7.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/workbox-build/node_modules/upath": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
+ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
+ "dev": true,
+ "engines": {
+ "node": ">=4",
+ "yarn": "*"
+ }
+ },
+ "node_modules/workbox-cacheable-response": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.4.tgz",
+ "integrity": "sha512-DCR9uD0Fqj8oB2TSWQEm1hbFs/85hXXoayVwFKLVuIuxwJaihBsLsp4y7J9bvZbqtPJ1KlCkmYVGQKrBU4KAug==",
+ "dev": true,
+ "dependencies": {
+ "workbox-core": "6.5.4"
+ }
+ },
+ "node_modules/workbox-core": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.4.tgz",
+ "integrity": "sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==",
+ "dev": true
+ },
+ "node_modules/workbox-expiration": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.4.tgz",
+ "integrity": "sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==",
+ "dev": true,
+ "dependencies": {
+ "idb": "^7.0.1",
+ "workbox-core": "6.5.4"
+ }
+ },
+ "node_modules/workbox-google-analytics": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.4.tgz",
+ "integrity": "sha512-8AU1WuaXsD49249Wq0B2zn4a/vvFfHkpcFfqAFHNHwln3jK9QUYmzdkKXGIZl9wyKNP+RRX30vcgcyWMcZ9VAg==",
+ "dev": true,
+ "dependencies": {
+ "workbox-background-sync": "6.5.4",
+ "workbox-core": "6.5.4",
+ "workbox-routing": "6.5.4",
+ "workbox-strategies": "6.5.4"
+ }
+ },
+ "node_modules/workbox-navigation-preload": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.4.tgz",
+ "integrity": "sha512-IIwf80eO3cr8h6XSQJF+Hxj26rg2RPFVUmJLUlM0+A2GzB4HFbQyKkrgD5y2d84g2IbJzP4B4j5dPBRzamHrng==",
+ "dev": true,
+ "dependencies": {
+ "workbox-core": "6.5.4"
+ }
+ },
+ "node_modules/workbox-precaching": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.4.tgz",
+ "integrity": "sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==",
+ "dev": true,
+ "dependencies": {
+ "workbox-core": "6.5.4",
+ "workbox-routing": "6.5.4",
+ "workbox-strategies": "6.5.4"
+ }
+ },
+ "node_modules/workbox-range-requests": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.5.4.tgz",
+ "integrity": "sha512-Je2qR1NXCFC8xVJ/Lux6saH6IrQGhMpDrPXWZWWS8n/RD+WZfKa6dSZwU+/QksfEadJEr/NfY+aP/CXFFK5JFg==",
+ "dev": true,
+ "dependencies": {
+ "workbox-core": "6.5.4"
+ }
+ },
+ "node_modules/workbox-recipes": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.4.tgz",
+ "integrity": "sha512-QZNO8Ez708NNwzLNEXTG4QYSKQ1ochzEtRLGaq+mr2PyoEIC1xFW7MrWxrONUxBFOByksds9Z4//lKAX8tHyUA==",
+ "dev": true,
+ "dependencies": {
+ "workbox-cacheable-response": "6.5.4",
+ "workbox-core": "6.5.4",
+ "workbox-expiration": "6.5.4",
+ "workbox-precaching": "6.5.4",
+ "workbox-routing": "6.5.4",
+ "workbox-strategies": "6.5.4"
+ }
+ },
+ "node_modules/workbox-routing": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.4.tgz",
+ "integrity": "sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==",
+ "dev": true,
+ "dependencies": {
+ "workbox-core": "6.5.4"
+ }
+ },
+ "node_modules/workbox-strategies": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.4.tgz",
+ "integrity": "sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==",
+ "dev": true,
+ "dependencies": {
+ "workbox-core": "6.5.4"
+ }
+ },
+ "node_modules/workbox-streams": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.4.tgz",
+ "integrity": "sha512-FXKVh87d2RFXkliAIheBojBELIPnWbQdyDvsH3t74Cwhg0fDheL1T8BqSM86hZvC0ZESLsznSYWw+Va+KVbUzg==",
+ "dev": true,
+ "dependencies": {
+ "workbox-core": "6.5.4",
+ "workbox-routing": "6.5.4"
+ }
+ },
+ "node_modules/workbox-sw": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.4.tgz",
+ "integrity": "sha512-vo2RQo7DILVRoH5LjGqw3nphavEjK4Qk+FenXeUsknKn14eCNedHOXWbmnvP4ipKhlE35pvJ4yl4YYf6YsJArA==",
+ "dev": true
+ },
+ "node_modules/workbox-window": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.5.4.tgz",
+ "integrity": "sha512-HnLZJDwYBE+hpG25AQBO8RUWBJRaCsI9ksQJEp3aCOFCaG5kqaToAYXFRAHxzRluM2cQbGzdQF5rjKPWPA1fug==",
+ "dev": true,
+ "dependencies": {
+ "@types/trusted-types": "^2.0.2",
+ "workbox-core": "6.5.4"
+ }
+ },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index f3e9cc81a..76c33a2ef 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "romm",
- "version": "1.7.1",
+ "version": "1.8",
"private": true,
"scripts": {
"dev": "vite --host",
@@ -15,10 +15,11 @@
"file-saver": "^2.0.5",
"jszip": "^3.10.1",
"mitt": "^3.0.0",
+ "pinia": "^2.0.35",
"roboto-fontface": "*",
"vue": "^3.2.13",
"vue-router": "^4.0.0",
- "vuetify": "^3.0.0",
+ "vuetify": "^3.1.15",
"webfontloader": "^1.0.0"
},
"devDependencies": {
@@ -28,6 +29,8 @@
"eslint-plugin-vue": "^9.3.0",
"sass": "^1.55.0",
"vite": "^3.1.9",
+ "vite-plugin-pwa": "^0.14.7",
+ "vite-plugin-rewrite-all": "^1.0.1",
"vite-plugin-vuetify": "^1.0.0-alpha.12"
}
}
diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico
new file mode 100644
index 000000000..47aded8d2
Binary files /dev/null and b/frontend/public/favicon.ico differ
diff --git a/frontend/public/favicon.svg b/frontend/public/favicon.svg
deleted file mode 100644
index 48a228114..000000000
--- a/frontend/public/favicon.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index d826b65b7..5987ab2fd 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -1,28 +1,41 @@
-
+
-
-
-
+
@@ -30,7 +43,7 @@ emitter.on('refresh', () => { refresh.value = !refresh.value })
-
+
@@ -58,25 +71,4 @@ emitter.on('refresh', () => { refresh.value = !refresh.value })
background-color: #808080;
border-radius: 5px;
}
-
-rommDark {
- primary: #161b22;
- secondary: #a452fe;
- background: #0d1117;
-
- notification: #0d1117;
- surface: #161b22;
- tooltip: #161b22;
- chip: #161b22;
-
- rommAccent1: #a452fe;
- rommAccent2: #9a00ea;
- rommAccent3: #7b00e1;
- rommAccent4: #702bcf;
- rommAccent5: #3808a4;
- rommWhite: #fefdfe;
- rommBlack: #000000;
- rommRed: #da3633;
-}
-
diff --git a/frontend/src/components/AppBar/Base.vue b/frontend/src/components/AppBar/Base.vue
index 4263d414b..8d1501494 100644
--- a/frontend/src/components/AppBar/Base.vue
+++ b/frontend/src/components/AppBar/Base.vue
@@ -1,45 +1,29 @@
-
+
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/frontend/src/components/AppBar/Gallery/Base.vue b/frontend/src/components/AppBar/Gallery/Base.vue
new file mode 100644
index 000000000..fe71b1ed9
--- /dev/null
+++ b/frontend/src/components/AppBar/Gallery/Base.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/components/AppBar/Gallery/FilterBar.vue b/frontend/src/components/AppBar/Gallery/FilterBar.vue
new file mode 100644
index 000000000..444dbc515
--- /dev/null
+++ b/frontend/src/components/AppBar/Gallery/FilterBar.vue
@@ -0,0 +1,27 @@
+
+
+
+
+
diff --git a/frontend/src/components/AppBar/Gallery/FilterBtn.vue b/frontend/src/components/AppBar/Gallery/FilterBtn.vue
new file mode 100644
index 000000000..60396ea9f
--- /dev/null
+++ b/frontend/src/components/AppBar/Gallery/FilterBtn.vue
@@ -0,0 +1,18 @@
+
+
+
+
+ mdi-magnify
+
+
diff --git a/frontend/src/components/AppBar/Gallery/GalleryViewBtn.vue b/frontend/src/components/AppBar/Gallery/GalleryViewBtn.vue
new file mode 100644
index 000000000..099c6b5ea
--- /dev/null
+++ b/frontend/src/components/AppBar/Gallery/GalleryViewBtn.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/AppBar/Gallery/MainDrawerToggle.vue b/frontend/src/components/AppBar/Gallery/MainDrawerToggle.vue
new file mode 100644
index 000000000..69dd09f87
--- /dev/null
+++ b/frontend/src/components/AppBar/Gallery/MainDrawerToggle.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/AppBar/GalleryViewBtn.vue b/frontend/src/components/AppBar/GalleryViewBtn.vue
deleted file mode 100644
index f352fa09c..000000000
--- a/frontend/src/components/AppBar/GalleryViewBtn.vue
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/frontend/src/components/AppBar/PlatformsBtn.vue b/frontend/src/components/AppBar/PlatformsBtn.vue
deleted file mode 100644
index 6f0572b62..000000000
--- a/frontend/src/components/AppBar/PlatformsBtn.vue
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/frontend/src/components/AppBar/SearchBar.vue b/frontend/src/components/AppBar/SearchBar.vue
deleted file mode 100644
index f16c45cc9..000000000
--- a/frontend/src/components/AppBar/SearchBar.vue
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
diff --git a/frontend/src/components/AppBar/SettingsBtn.vue b/frontend/src/components/AppBar/SettingsBtn.vue
deleted file mode 100644
index 331d47d16..000000000
--- a/frontend/src/components/AppBar/SettingsBtn.vue
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
- mdi-cog
-
-
\ No newline at end of file
diff --git a/frontend/src/components/AppBar/UploadBtn.vue b/frontend/src/components/AppBar/UploadBtn.vue
deleted file mode 100644
index 750e80fbc..000000000
--- a/frontend/src/components/AppBar/UploadBtn.vue
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
- mdi-upload
-
-
\ No newline at end of file
diff --git a/frontend/src/components/GameDetails/BackgroundHeader.vue b/frontend/src/components/GameDetails/BackgroundHeader.vue
index 5ad31453e..b40ef00bc 100644
--- a/frontend/src/components/GameDetails/BackgroundHeader.vue
+++ b/frontend/src/components/GameDetails/BackgroundHeader.vue
@@ -4,7 +4,7 @@ const props = defineProps(['rom'])
diff --git a/frontend/src/components/GameGallery/Card/ActionBar.vue b/frontend/src/components/GameGallery/Card/ActionBar.vue
index 71076bf9e..5eb9b2f4a 100644
--- a/frontend/src/components/GameGallery/Card/ActionBar.vue
+++ b/frontend/src/components/GameGallery/Card/ActionBar.vue
@@ -1,6 +1,6 @@
diff --git a/frontend/src/components/GameGallery/Card/Cover.vue b/frontend/src/components/GameGallery/Card/Cover.vue
index 2a62c2270..0279aed91 100644
--- a/frontend/src/components/GameGallery/Card/Cover.vue
+++ b/frontend/src/components/GameGallery/Card/Cover.vue
@@ -1,54 +1,50 @@
-
-
-
-
-
-
-
-
- {{ rom.file_name }}
-
-
-
-
- {{ rom.region }}
-
-
- {{ rom.revision }}
-
-
-
+
+
+
+
+
+
+
+
+
+ {{ rom.file_name }}
+
+
+
+
+ {{ rom.region }}
+
+
+ {{ rom.revision }}
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/MainDrawer/Platform.vue b/frontend/src/components/MainDrawer/Platform.vue
new file mode 100644
index 000000000..4d796739f
--- /dev/null
+++ b/frontend/src/components/MainDrawer/Platform.vue
@@ -0,0 +1,21 @@
+
+
+
+
+ {{ rail ? '' : platform.name }}
+
+
+
+
+ {{ platform.n_roms }}
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/PlatformsDrawer/RailBtn.vue b/frontend/src/components/MainDrawer/RailBtn.vue
similarity index 82%
rename from frontend/src/components/PlatformsDrawer/RailBtn.vue
rename to frontend/src/components/MainDrawer/RailBtn.vue
index 713844969..58d15e8c6 100644
--- a/frontend/src/components/PlatformsDrawer/RailBtn.vue
+++ b/frontend/src/components/MainDrawer/RailBtn.vue
@@ -10,8 +10,9 @@ const emitter = inject('emitter')
mdi-arrow-collapse-right
mdi-arrow-collapse-left
diff --git a/frontend/src/components/Notification.vue b/frontend/src/components/Notification.vue
index e3ea8f611..9ea53b56a 100644
--- a/frontend/src/components/Notification.vue
+++ b/frontend/src/components/Notification.vue
@@ -14,7 +14,7 @@ emitter.on('snackbarScan', (snackbar) => {
-
+
{{ snackbarStatus.msg }}
diff --git a/frontend/src/components/PlatformsDrawer/Base.vue b/frontend/src/components/PlatformsDrawer/Base.vue
deleted file mode 100644
index e0644bad5..000000000
--- a/frontend/src/components/PlatformsDrawer/Base.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/frontend/src/components/PlatformsDrawer/Platform.vue b/frontend/src/components/PlatformsDrawer/Platform.vue
deleted file mode 100644
index bb603c9a5..000000000
--- a/frontend/src/components/PlatformsDrawer/Platform.vue
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
- {{ rail ? '' : platform.name }}
-
-
-
-
- {{ platform.n_roms }}
-
-
-
-
-
\ No newline at end of file
diff --git a/frontend/src/components/SettingsDrawer/Base.vue b/frontend/src/components/SettingsDrawer/Base.vue
deleted file mode 100644
index 27f90a4e2..000000000
--- a/frontend/src/components/SettingsDrawer/Base.vue
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/frontend/src/components/SettingsDrawer/Header.vue b/frontend/src/components/SettingsDrawer/Header.vue
deleted file mode 100644
index 0a2fa6ed0..000000000
--- a/frontend/src/components/SettingsDrawer/Header.vue
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
- Settings
-
-
-
\ No newline at end of file
diff --git a/frontend/src/components/SettingsDrawer/Scan.vue b/frontend/src/components/SettingsDrawer/Scan.vue
deleted file mode 100644
index be5e281f3..000000000
--- a/frontend/src/components/SettingsDrawer/Scan.vue
+++ /dev/null
@@ -1,80 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Scan
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/frontend/src/components/SettingsDrawer/ThemeToggle.vue b/frontend/src/components/SettingsDrawer/ThemeToggle.vue
deleted file mode 100644
index f83d29fc4..000000000
--- a/frontend/src/components/SettingsDrawer/ThemeToggle.vue
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/frontend/src/components/SettingsDrawer/VersionLabel.vue b/frontend/src/components/SettingsDrawer/VersionLabel.vue
deleted file mode 100644
index 5237aa6bd..000000000
--- a/frontend/src/components/SettingsDrawer/VersionLabel.vue
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
- RomM v{{ ROMM_VERSION }}
-
-
\ No newline at end of file
diff --git a/frontend/src/plugins/index.js b/frontend/src/plugins/index.js
index 497422327..43c10d05d 100644
--- a/frontend/src/plugins/index.js
+++ b/frontend/src/plugins/index.js
@@ -7,11 +7,13 @@
// Plugins
import { loadFonts } from './webfontloader'
import vuetify from './vuetify'
-import router from '../router'
+import router from './router'
+import pinia from './pinia'
export function registerPlugins (app) {
loadFonts()
app
.use(vuetify)
.use(router)
+ .use(pinia)
}
diff --git a/frontend/src/plugins/pinia.js b/frontend/src/plugins/pinia.js
new file mode 100644
index 000000000..8a0598063
--- /dev/null
+++ b/frontend/src/plugins/pinia.js
@@ -0,0 +1,5 @@
+import { createPinia } from 'pinia'
+
+const pinia = createPinia()
+
+export default pinia
diff --git a/frontend/src/router/index.js b/frontend/src/plugins/router.js
similarity index 50%
rename from frontend/src/router/index.js
rename to frontend/src/plugins/router.js
index fae2377e8..02eef3322 100644
--- a/frontend/src/router/index.js
+++ b/frontend/src/plugins/router.js
@@ -4,11 +4,23 @@ import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
+ component: () => import('@/views/Home.vue')
+ },
+ {
+ path: '/platform/:platform',
component: () => import('@/views/Gallery.vue')
},
{
- path: '/details',
+ path: '/platform/:platform/rom/:rom',
component: () => import('@/views/Details.vue')
+ },
+ {
+ path: '/library/scan',
+ component: () => import('@/views/library/Scan.vue')
+ },
+ {
+ path: '/settings/control-panel',
+ component: () => import('@/views/settings/ControlPanel.vue')
}
]
diff --git a/frontend/src/plugins/vuetify.js b/frontend/src/plugins/vuetify.js
index 32ca4e2d6..3b3dea398 100644
--- a/frontend/src/plugins/vuetify.js
+++ b/frontend/src/plugins/vuetify.js
@@ -7,53 +7,11 @@
// Styles
import '@mdi/font/css/materialdesignicons.css'
import 'vuetify/styles'
+import { rommDark, rommLight } from '@/styles/themes.js'
// Composables
import { createVuetify } from 'vuetify'
-const rommDark = {
- dark: true,
- colors: {
- primary: '#161b22',
- secondary: '#a452fe',
- background: '#0d1117',
-
- notification: '#0d1117',
- surface: '#161b22',
- tooltip: '#161b22',
- chip: '#161b22',
-
- rommAccent1: '#a452fe',
- rommAccent2: '#c400f7',
- rommAccent2: '#3808a4',
- rommWhite: '#fefdfe',
- rommBlack: '#000000',
- rommRed: '#da3633',
- rommGreen: '#3FB950'
- }
-}
-const rommLight = {
- dark: false,
- colors: {
- primary: '#fefdfe',
- secondary: '#a452fe',
- background: '#fefdfe',
-
- notification: '#0d1117',
- surface: '#fefdfe',
- tooltip: '#fefdfe',
- chip: '#161b22',
-
- rommAccent1: '#a452fe',
- rommAccent2: '#c400f7',
- rommAccent2: '#3808a4',
- rommWhite: '#fefdfe',
- rommBlack: '#000000',
- rommRed: '#da3633',
- rommGreen: '#3FB950'
- }
-}
-
export default createVuetify({
icons: {
iconfont: 'mdi'
diff --git a/frontend/src/services/api.js b/frontend/src/services/api.js
new file mode 100644
index 000000000..d97d00dcd
--- /dev/null
+++ b/frontend/src/services/api.js
@@ -0,0 +1,6 @@
+import axios from 'axios'
+
+
+export async function getPlatforms () {
+ return axios.get('/api/platforms')
+}
diff --git a/frontend/src/services/download.js b/frontend/src/services/download.js
new file mode 100644
index 000000000..4ad652f5d
--- /dev/null
+++ b/frontend/src/services/download.js
@@ -0,0 +1,36 @@
+import JSZip from "jszip"
+import { saveAs } from 'file-saver'
+import { storeDownloader } from '@/stores/downloader.js'
+
+const downloader = storeDownloader()
+
+export async function downloadRom(rom, emitter, filesToDownload=[]) {
+ downloader.add(rom.file_name)
+ emitter.emit('snackbarScan', {'msg': "Downloading "+rom.file_name+"...", 'icon': 'mdi-download', 'color': 'green'})
+ if(rom.multi){
+ const zip = new JSZip()
+ var zipFilename = rom.file_name+".zip"
+ var files = []
+ filesToDownload.forEach(f => {files.push(f)})
+ if (files.length == 0){ files = rom.files }
+ var count = 0
+ files.forEach(async function (file_part) {
+ var file_full_path = "/assets"+rom.file_path+"/"+rom.file_name+"/"+file_part
+ var file = await fetch(file_full_path)
+ var fileBlob = await file.blob()
+ var f = zip.folder(rom.file_name);
+ f.file(file_part, fileBlob, { binary: true });
+ count ++
+ if (count == files.length) { zip.generateAsync({ type: 'blob' }).then(function (content) { saveAs(content, zipFilename); }); }
+ })
+ }
+ else{
+ var file_full_path = "/assets"+rom.file_path+"/"+rom.file_name
+ var file = await fetch(file_full_path)
+ var fileBlob = await file.blob()
+ saveAs(fileBlob, rom.file_name)
+ }
+ downloader.remove(rom.file_name)
+}
+
+export async function downloadSave(rom) { console.log("Downloading "+rom.file_name+" save file") }
\ No newline at end of file
diff --git a/frontend/src/stores/contextBar.js b/frontend/src/stores/contextBar.js
new file mode 100644
index 000000000..8fb7f9c43
--- /dev/null
+++ b/frontend/src/stores/contextBar.js
@@ -0,0 +1,9 @@
+import { defineStore } from 'pinia'
+
+export const storeContextBar = defineStore('contextBar', {
+ state: () => ({ value: false }),
+
+ actions: {
+ toggleContextBar() { this.value = !this.value }
+ }
+})
\ No newline at end of file
diff --git a/frontend/src/stores/downloader.js b/frontend/src/stores/downloader.js
new file mode 100644
index 000000000..12e45d4fe
--- /dev/null
+++ b/frontend/src/stores/downloader.js
@@ -0,0 +1,10 @@
+import { defineStore } from 'pinia'
+
+export const storeDownloader = defineStore('downloader', {
+ state: () => ({ value: [] }),
+
+ actions: {
+ add(rom) { this.value.push(rom) },
+ remove(rom) { this.value.splice(this.value.indexOf(rom), 1) }
+ }
+})
\ No newline at end of file
diff --git a/frontend/src/stores/filter.js b/frontend/src/stores/filter.js
new file mode 100644
index 000000000..92492c29c
--- /dev/null
+++ b/frontend/src/stores/filter.js
@@ -0,0 +1,10 @@
+import { defineStore } from 'pinia'
+import { normalizeString } from '@/utils/utils.js'
+
+export const storeFilter = defineStore('filter', {
+ state: () => ({ value: '' }),
+
+ actions: {
+ set(filter) { this.value = normalizeString(filter) }
+ }
+})
\ No newline at end of file
diff --git a/frontend/src/stores/galleryView.js b/frontend/src/stores/galleryView.js
new file mode 100644
index 000000000..9329ac254
--- /dev/null
+++ b/frontend/src/stores/galleryView.js
@@ -0,0 +1,16 @@
+import { defineStore } from 'pinia'
+
+export const storeGalleryView = defineStore('galleryView', {
+ state: () => ({ value: (JSON.parse(localStorage.getItem('currentView')) || 0)}),
+
+ actions: {
+ set(view) {
+ this.value = view
+ localStorage.setItem('currentView', this.value)
+ },
+ next(){
+ if(this.value == 2){this.set(0)}
+ else{this.set(this.value+1)}
+ }
+ }
+})
\ No newline at end of file
diff --git a/frontend/src/stores/platforms.js b/frontend/src/stores/platforms.js
new file mode 100644
index 000000000..0a57c3c5c
--- /dev/null
+++ b/frontend/src/stores/platforms.js
@@ -0,0 +1,11 @@
+import { defineStore } from 'pinia'
+
+export const storePlatforms = defineStore('platforms', {
+ state: () => ({ value: [] }),
+
+ actions: {
+ add(platforms) {
+ this.value = platforms
+ }
+ }
+})
\ No newline at end of file
diff --git a/frontend/src/stores/scanning.js b/frontend/src/stores/scanning.js
new file mode 100644
index 000000000..3d7bdf19d
--- /dev/null
+++ b/frontend/src/stores/scanning.js
@@ -0,0 +1,9 @@
+import { defineStore } from 'pinia'
+
+export const storeScanning = defineStore('scanning', {
+ state: () => ({ value: false }),
+
+ actions: {
+ set(scanning) { this.value = scanning }
+ }
+})
\ No newline at end of file
diff --git a/frontend/src/styles/themes.js b/frontend/src/styles/themes.js
new file mode 100644
index 000000000..4e49aa673
--- /dev/null
+++ b/frontend/src/styles/themes.js
@@ -0,0 +1,45 @@
+export const rommDark = {
+ dark: true,
+ colors: {
+ primary: '#161b22',
+ secondary: '#0d1117',
+ terciary: '#202832',
+ background: '#0d1117',
+
+ surface: '#161b22',
+ tooltip: '#161b22',
+ chip: '#161b22',
+
+ rommAccent1: '#a452fe',
+ rommAccent2: '#c400f7',
+ rommAccent3: '#3808a4',
+
+ rommRed: '#da3633',
+ rommGreen: '#3FB950',
+ rommWhite: '#fefdfe',
+ rommBlack: '#000000',
+ }
+}
+
+export const rommLight = {
+ dark: false,
+ colors: {
+ primary: '#fefdfe',
+ secondary: '#fefdfe',
+ terciary: '#fefdfe',
+ background: '#fefdfe',
+
+ surface: '#fefdfe',
+ tooltip: '#fefdfe',
+ chip: '#fefdfe',
+
+ rommAccent1: '#a452fe',
+ rommAccent2: '#c400f7',
+ rommAccent3: '#3808a4',
+
+ rommRed: '#da3633',
+ rommGreen: '#3FB950',
+ rommWhite: '#fefdfe',
+ rommBlack: '#000000',
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/utils/utils.js b/frontend/src/utils/utils.js
index 4cd4cc0ea..bf4cbd040 100644
--- a/frontend/src/utils/utils.js
+++ b/frontend/src/utils/utils.js
@@ -1,48 +1,7 @@
-import JSZip from "jszip"
-import { toRaw } from "vue"
-import { saveAs } from 'file-saver'
-
-
-
-export async function selectRom(rom, emitter, router) {
- localStorage.setItem('currentRom', JSON.stringify(rom))
- await router.push(import.meta.env.BASE_URL+'details')
- emitter.emit('currentRom', rom)
-}
-
-export async function downloadRom(rom, emitter, filesToDownload=[]) {
- emitter.emit('snackbarScan', {'msg': "Downloading "+rom.file_name+"...", 'icon': 'mdi-download', 'color': 'green'})
- if(rom.multi){
- const zip = new JSZip()
- var zipFilename = rom.file_name+".zip"
- var files = []
- toRaw(filesToDownload).forEach(f => {files.push(toRaw(f))})
- if (files.length == 0){ files = rom.files }
- var count = 0
- files.forEach(async function (file_part) {
- var file_full_path = "/assets"+rom.file_path+"/"+rom.file_name+"/"+file_part
- var file = await fetch(file_full_path)
- var fileBlob = await file.blob()
- var f = zip.folder(rom.file_name);
- f.file(file_part, fileBlob, { binary: true });
- count ++
- if (count == files.length) { zip.generateAsync({ type: 'blob' }).then(function (content) { saveAs(content, zipFilename); }); }
- })
- }
- else{
- var file_full_path = "/assets"+rom.file_path+"/"+rom.file_name
- var file = await fetch(file_full_path)
- var fileBlob = await file.blob()
- saveAs(fileBlob, rom.file_name)
- }
-}
-
-export async function downloadSave(rom, emitter) { console.log("Downloading "+rom.file_name+" save file") }
-
-export function normalizeString(s) { return s.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g,"") }
-
export const views = {
0:{'view': 'small', 'icon': 'mdi-view-module', 'size-lg': 1, 'size-md': 2, 'size-sm': 2, 'size-xs': 3, 'size-cols': 4},
1:{'view': 'big', 'icon': 'mdi-view-list', 'size-lg': 2, 'size-md': 3, 'size-sm': 3, 'size-xs': 6, 'size-cols': 6},
2:{'view': 'list', 'icon': 'mdi-view-comfy', 'size-lg': 1, 'size-md': 2, 'size-sm': 2, 'size-xs': 3, 'size-cols': 4}
}
+
+export function normalizeString(s) { return s.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g,"") }
\ No newline at end of file
diff --git a/frontend/src/views/Details.vue b/frontend/src/views/Details.vue
index c67c100f8..bb65d2a6f 100644
--- a/frontend/src/views/Details.vue
+++ b/frontend/src/views/Details.vue
@@ -1,33 +1,37 @@
-
+
-
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
+
-
+
@@ -144,50 +149,50 @@ async function deleteRom() {
-
- Info
- Saves
- Screenshots
+
+ Info
+ Saves
+ Screenshots
- File
- {{ rom.file_name }}
+ File
+ {{ rom.file_name }}
- Files
+ Files
- Size
- {{ rom.file_size }} {{ rom.file_size_units }}
+ Size
+ {{ rom.file_size }} {{ rom.file_size_units }}
- IGDB
+ IGDB
{{ rom.r_igdb_id }}
- Tags
- {{ tag }}
+ Tags
+ {{ tag }}
{{ rom.summary }}
@@ -208,10 +213,10 @@ async function deleteRom() {
-
+
-
+
Searching...
Results found
mdi-close
@@ -219,7 +224,7 @@ async function deleteRom() {
-
+
-
- No results found
+
+ No results found
-
+
-
+
- {{ rom.name }}
+ {{ rom.r_name }}
@@ -261,35 +266,38 @@ async function deleteRom() {
-
+
-
- Editing {{ rom.file_name }}
+
+ Editing
mdi-close
-
+
-
+
- Apply
+
+ Apply
+ Cancel
+
-
+
-
+
Deleting {{ rom.file_name }}
mdi-close
-
+
Deleting from RomM. Do you confirm?
@@ -307,8 +315,8 @@ async function deleteRom() {
-
-
+
+
@@ -318,6 +326,7 @@ async function deleteRom() {
overflow-y: scroll
}
.content, .content-tablet{
+ margin-top: 64px;
margin-left: 100px;
margin-right: 100px;
}
@@ -334,7 +343,7 @@ async function deleteRom() {
padding-left: 25px;
padding-right: 25px;
}
-.info-header{
+.rom-name, .rom-platform {
text-shadow: 1px 1px 3px #000000, 0 0 3px #000000;
}
.info-content{
diff --git a/frontend/src/views/Gallery.vue b/frontend/src/views/Gallery.vue
index e04f1a869..aa690c179 100644
--- a/frontend/src/views/Gallery.vue
+++ b/frontend/src/views/Gallery.vue
@@ -1,78 +1,98 @@
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+ Feels cold here... mdi-emoticon-sad
+
-
+
diff --git a/frontend/src/views/Home.vue b/frontend/src/views/Home.vue
new file mode 100644
index 000000000..de888d46a
--- /dev/null
+++ b/frontend/src/views/Home.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+ Total games: {{ totalGames }}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/views/library/Scan.vue b/frontend/src/views/library/Scan.vue
new file mode 100644
index 000000000..e21dac106
--- /dev/null
+++ b/frontend/src/views/library/Scan.vue
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+ Scan
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/views/settings/ControlPanel.vue b/frontend/src/views/settings/ControlPanel.vue
new file mode 100644
index 000000000..1823523fa
--- /dev/null
+++ b/frontend/src/views/settings/ControlPanel.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+ General{{ rail ? '' : '[comming soon]' }}
+ User Interface
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ RomM v{{ ROMM_VERSION }}
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index eecdd9dba..242082fda 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -1,6 +1,8 @@
// Plugins
import vue from '@vitejs/plugin-vue'
import vuetify, { transformAssetUrls } from 'vite-plugin-vuetify'
+import { VitePWA } from 'vite-plugin-pwa'
+import pluginRewriteAll from 'vite-plugin-rewrite-all'
// Utilities
import { defineConfig } from 'vite'
@@ -9,16 +11,28 @@ import { fileURLToPath, URL } from 'node:url'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
+ pluginRewriteAll(),
vue({
template: { transformAssetUrls }
}),
- // https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin
vuetify({
autoImport: true,
styles: {
configFile: 'src/styles/settings.scss',
},
}),
+ VitePWA({
+ manifest: {
+ icons: [
+ {
+ src: "favicon.ico",
+ sizes: "256x256",
+ type: "image/ico",
+ purpose: "any maskable"
+ }
+ ]
+ }
+ })
],
define: { 'process.env': {} },
resolve: {
diff --git a/romm.svg b/romm.svg
index a1330c532..13fa4d7ec 100644
--- a/romm.svg
+++ b/romm.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file