From 576fb32faa9379fd24110814945cd250bac938df Mon Sep 17 00:00:00 2001 From: MoritzWeber Date: Fri, 26 May 2023 13:57:30 +0200 Subject: [PATCH] feat: Add support for plugins The System engineering toolchain team for Digitale Schiene is offering several model modifiers and model derivative jobs. Example for model modifiers are: - ID injection bot (inject IDs into model elements) Example for model derivates: - Model complexity badge generation - Diagram cache generation - Automatic documentation generation Synchronisation between TeamForCapella and Git is also considered as job, somewhere in between. Currently, all "jobs" are run in the Gitlab CI. There is no UI for the setup of these jobs. Each job repository provides a Gitlab CI templates, which can be easily integrated in project repositories. However, this approach is not intuitive for external people, leading to operation support effort for operation teams, which have to take care of the creation and updates of jobs. Another disadavantage of the current approach is the Gitlab dependency. Not all environments have a Gitlab instance available. Getting it running on other platforms is even more effort. This commit adds a plugin/job store to the Capella Colloration Manager. A plugin/job is still developed in a Git repository. Plugins have to define a `mbse-works-plugin.yml`, providing metadata, input, output, trigger and job information. The JSON schema can be fetched via `GET /api/v1.0/plugins-schema` (backend). A human-readable documentation is available via `/docs/plugin-schema` (backend). With this information, registered plugins can be easily integrated into projects. The integration should be intuitive for project leads. The steps are: - Create a new pipeline - Select a supported plugin from the store - Configure the plugin: Supported types for the beginning are: - git (Select a linked git model from the project, so that the job can access the Git repository information) - t4c (Select a linked T4C repository/project from the project). The job gets the connection information + a session token. - yml (Most flexible option, the yml configuration file is mounted into the job container, validation via yml schema) - environment (Key/value pairs, which are used as environment variable for the job) - Confirm the creation As part of this commit, there are only two options: - Run the pipeline manually - Run it as 3am during the night. Co-authored-by: ewuerger Co-authored-by: Paula-Kli --- backend/Makefile | 6 + backend/capellacollab/__main__.py | 17 +- .../e3f1006f6b49_add_plugins_table.py | 34 + .../capellacollab/core/database/__init__.py | 5 +- backend/capellacollab/core/database/models.py | 5 +- backend/capellacollab/health/models.py | 6 +- backend/capellacollab/health/routes.py | 2 +- .../backups => plugins}/__init__.py | 0 backend/capellacollab/plugins/crud.py | 62 + backend/capellacollab/plugins/injectables.py | 23 + backend/capellacollab/plugins/models.py | 267 ++ backend/capellacollab/plugins/routes.py | 157 + backend/capellacollab/plugins/schema.py | 49 + backend/capellacollab/projects/routes.py | 9 +- .../toolmodels/modelsources/git/routes.py | 2 +- .../toolmodels/modelsources/t4c/routes.py | 2 +- .../{backups/runs => pipelines}/__init__.py | 0 .../toolmodels/{backups => pipelines}/core.py | 4 + .../toolmodels/{backups => pipelines}/crud.py | 4 +- .../{backups => pipelines}/exceptions.py | 0 .../{backups => pipelines}/injectables.py | 0 .../{backups => pipelines}/models.py | 12 +- .../{backups => pipelines}/routes.py | 0 .../toolmodels/pipelines/runs/__init__.py | 2 + .../{backups => pipelines}/runs/crud.py | 0 .../{backups => pipelines}/runs/helper.py | 0 .../runs/injectables.py | 6 +- .../{backups => pipelines}/runs/interface.py | 2 +- .../{backups => pipelines}/runs/models.py | 0 .../{backups => pipelines}/runs/routes.py | 0 .../{backups => pipelines}/validation.py | 0 .../projects/toolmodels/routes.py | 8 +- backend/capellacollab/routes.py | 15 +- backend/capellacollab/settings/routes.py | 4 +- backend/plugin_schema.yml | 4 + backend/plugin_schema/plugin_schema.html | 12 + backend/plugin_schema/schema_doc.css | 186 + backend/plugin_schema/schema_doc.min.js | 6 + backend/pyproject.toml | 3 + .../data/mbse-works-plugins/hello-world.yml | 14 + .../data/mbse-works-plugins/t4c-to-git.yml | 52 + .../projects/toolmodels/pipelines/conftest.py | 8 +- .../pipelines/pipeline-runs/conftest.py | 6 +- .../pipeline-runs/test_pipeline_runs.py | 24 +- .../toolmodels/pipelines/test_pipelines.py | 14 +- frontend/package-lock.json | 3154 +++++++---------- frontend/package.json | 2 + frontend/src/app/app-routing.module.ts | 85 +- frontend/src/app/app.component.css | 4 + frontend/src/app/app.module.ts | 22 +- .../app/general/nav-bar/nav-bar.service.ts | 5 + .../create-plugin.component.spec.ts | 27 + .../create-plugin/create-plugin.component.ts | 23 + .../edit-plugin/edit-plugin.component.css} | 0 .../edit-plugin/edit-plugin.component.html | 75 + .../edit-plugin/edit-plugin.component.ts | 83 + .../plugin-detail/plugin-details.component.ts | 82 + .../plugin-store-overview.component.css | 8 + .../plugin-store-overview.component.html | 43 + .../plugin-store-overview.component.ts | 16 + .../plugin-wrapper.component.css | 4 + .../plugin-wrapper.component.html | 6 + .../plugin-wrapper.component.ts | 49 + .../store/service/plugin-store.service.ts | 138 + .../create-backup.component.html | 73 - .../create-backup/create-backup.component.ts | 107 - .../create-pipeline.component.css | 13 + .../create-pipeline.component.html | 210 ++ .../create-pipeline.component.ts | 91 + .../pipeline-environment-input.component.css | 4 + .../pipeline-environment-input.component.html | 33 + ...peline-environment-input.component.spec.ts | 26 + .../pipeline-environment-input.component.ts | 51 + .../pipeline-git-input.component.css | 4 + .../pipeline-git-input.component.html | 53 + .../pipeline-git-input.component.spec.ts | 26 + .../pipeline-git-input.component.ts | 64 + .../pipeline-t4c-input.component.css | 4 + .../pipeline-t4c-input.component.html | 56 + .../pipeline-t4c-input.component.spec.ts | 26 + .../pipeline-t4c-input.component.ts | 64 + .../pipeline-triggers.component.css | 4 + .../pipeline-triggers.component.html | 33 + .../pipeline-triggers.component.spec.ts | 26 + .../pipeline-triggers.component.ts | 36 + .../service/pipeline.service.ts | 2 +- .../trigger-pipeline.component.html | 211 +- .../trigger-pipeline.component.ts | 98 +- .../model-overview.component.html | 4 +- .../model-overview.component.ts | 10 - .../app/projects/service/project.service.ts | 2 +- frontend/src/styles.css | 2 +- 92 files changed, 3807 insertions(+), 2384 deletions(-) create mode 100644 backend/capellacollab/alembic/versions/e3f1006f6b49_add_plugins_table.py rename backend/capellacollab/{projects/toolmodels/backups => plugins}/__init__.py (100%) create mode 100644 backend/capellacollab/plugins/crud.py create mode 100644 backend/capellacollab/plugins/injectables.py create mode 100644 backend/capellacollab/plugins/models.py create mode 100644 backend/capellacollab/plugins/routes.py create mode 100644 backend/capellacollab/plugins/schema.py rename backend/capellacollab/projects/toolmodels/{backups/runs => pipelines}/__init__.py (100%) rename backend/capellacollab/projects/toolmodels/{backups => pipelines}/core.py (97%) rename backend/capellacollab/projects/toolmodels/{backups => pipelines}/crud.py (92%) rename backend/capellacollab/projects/toolmodels/{backups => pipelines}/exceptions.py (100%) rename backend/capellacollab/projects/toolmodels/{backups => pipelines}/injectables.py (100%) rename backend/capellacollab/projects/toolmodels/{backups => pipelines}/models.py (83%) rename backend/capellacollab/projects/toolmodels/{backups => pipelines}/routes.py (100%) create mode 100644 backend/capellacollab/projects/toolmodels/pipelines/runs/__init__.py rename backend/capellacollab/projects/toolmodels/{backups => pipelines}/runs/crud.py (100%) rename backend/capellacollab/projects/toolmodels/{backups => pipelines}/runs/helper.py (100%) rename backend/capellacollab/projects/toolmodels/{backups => pipelines}/runs/injectables.py (89%) rename backend/capellacollab/projects/toolmodels/{backups => pipelines}/runs/interface.py (99%) rename backend/capellacollab/projects/toolmodels/{backups => pipelines}/runs/models.py (100%) rename backend/capellacollab/projects/toolmodels/{backups => pipelines}/runs/routes.py (100%) rename backend/capellacollab/projects/toolmodels/{backups => pipelines}/validation.py (100%) create mode 100644 backend/plugin_schema.yml create mode 100644 backend/plugin_schema/plugin_schema.html create mode 100644 backend/plugin_schema/schema_doc.css create mode 100644 backend/plugin_schema/schema_doc.min.js create mode 100644 backend/tests/data/mbse-works-plugins/hello-world.yml create mode 100644 backend/tests/data/mbse-works-plugins/t4c-to-git.yml create mode 100644 frontend/src/app/plugins/store/create-plugin/create-plugin.component.spec.ts create mode 100644 frontend/src/app/plugins/store/create-plugin/create-plugin.component.ts rename frontend/src/app/{projects/models/backup-settings/create-backup/create-backup.component.css => plugins/store/edit-plugin/edit-plugin.component.css} (100%) create mode 100644 frontend/src/app/plugins/store/edit-plugin/edit-plugin.component.html create mode 100644 frontend/src/app/plugins/store/edit-plugin/edit-plugin.component.ts create mode 100644 frontend/src/app/plugins/store/plugin-detail/plugin-details.component.ts create mode 100644 frontend/src/app/plugins/store/plugin-store-overview/plugin-store-overview.component.css create mode 100644 frontend/src/app/plugins/store/plugin-store-overview/plugin-store-overview.component.html create mode 100644 frontend/src/app/plugins/store/plugin-store-overview/plugin-store-overview.component.ts create mode 100644 frontend/src/app/plugins/store/plugin-wrapper/plugin-wrapper.component.css create mode 100644 frontend/src/app/plugins/store/plugin-wrapper/plugin-wrapper.component.html create mode 100644 frontend/src/app/plugins/store/plugin-wrapper/plugin-wrapper.component.ts create mode 100644 frontend/src/app/plugins/store/service/plugin-store.service.ts delete mode 100644 frontend/src/app/projects/models/backup-settings/create-backup/create-backup.component.html delete mode 100644 frontend/src/app/projects/models/backup-settings/create-backup/create-backup.component.ts create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/create-pipeline.component.css create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/create-pipeline.component.html create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/create-pipeline.component.ts create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.css create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.html create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.spec.ts create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.ts create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.css create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.html create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.spec.ts create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.ts create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.css create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.html create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.spec.ts create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.ts create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.css create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.html create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.spec.ts create mode 100644 frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.ts diff --git a/backend/Makefile b/backend/Makefile index a5d29f953..b18f4dec5 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -68,3 +68,9 @@ load: clear save: docker run -i -e PGPASSWORD=$(DB_PASSWORD) --network host --entrypoint="pg_dump" postgres:latest -h 'localhost' -p $(DB_PORT) -U '$(DB_USER)' $(DB_NAME) > $(DATABASE_SAVE_DIR)/$(shell date +"%FT%T").sql + +plugin-schema: + $(VENV)/bin/pip show json-schema-for-humans > /dev/null || $(VENV)/bin/pip install json-schema-for-humans + $(VENV)/bin/python -c 'import pathlib; import json; from capellacollab.plugins import models; pathlib.Path("plugin_schema.yml").write_text(json.dumps(models.PluginContent.model_json_schema()))' + mkdir -p plugin_schema + $(VENV)/bin/generate-schema-doc plugin_schema.yml plugin_schema/plugin_schema.html diff --git a/backend/capellacollab/__main__.py b/backend/capellacollab/__main__.py index 99fd90e87..738d184e5 100644 --- a/backend/capellacollab/__main__.py +++ b/backend/capellacollab/__main__.py @@ -9,10 +9,10 @@ import fastapi_pagination import starlette_prometheus import uvicorn -from fastapi import middleware, responses +from fastapi import middleware, responses, staticfiles from fastapi.middleware import cors -import capellacollab.projects.toolmodels.backups.runs.interface as pipeline_runs_interface +import capellacollab.projects.toolmodels.pipelines.runs.interface as pipeline_runs_interface import capellacollab.sessions.metrics # This import statement is required and should not be removed! (Alembic will not work otherwise) @@ -21,12 +21,10 @@ from capellacollab.core import logging as core_logging from capellacollab.core.database import engine, migration from capellacollab.core.logging import exceptions as logging_exceptions +from capellacollab.plugins import schema as pipeline_schema from capellacollab.projects.toolmodels import ( exceptions as toolmodels_exceptions, ) -from capellacollab.projects.toolmodels.backups import ( - exceptions as backups_exceptions, -) from capellacollab.projects.toolmodels.modelsources.git import ( exceptions as git_exceptions, ) @@ -36,6 +34,9 @@ from capellacollab.projects.toolmodels.modelsources.git.handler import ( exceptions as git_handler_exceptions, ) +from capellacollab.projects.toolmodels.pipelines import ( + exceptions as backups_exceptions, +) from capellacollab.routes import router from capellacollab.sessions import exceptions as sessions_exceptions from capellacollab.sessions import idletimeout, operators @@ -66,7 +67,7 @@ async def startup(): operators.get_operator() logging.getLogger("uvicorn.access").disabled = True - logging.getLogger("uvicorn.error").disabled = True + logging.getLogger("uvicorn.error").disabled = False logging.getLogger("requests_oauthlib.oauth2_session").setLevel("INFO") logging.getLogger("kubernetes.client.rest").setLevel("INFO") @@ -83,6 +84,7 @@ async def shutdown(): idletimeout.terminate_idle_sessions_in_background, capellacollab.sessions.metrics.register, pipeline_runs_interface.schedule_refresh_and_trigger_pipeline_jobs, + pipeline_schema.generate_schema_documentation, ], middleware=[ middleware.Middleware( @@ -98,7 +100,7 @@ async def shutdown(): middleware.Middleware(core_logging.LogRequestsMiddleware), middleware.Middleware(starlette_prometheus.PrometheusMiddleware), ], - on_shutdown=[shutdown], + on_shutdown=[shutdown, pipeline_schema.cleanup_documentation_directory], ) fastapi_pagination.add_pagination(app) @@ -135,6 +137,7 @@ async def healthcheck(): app.add_route("/metrics", starlette_prometheus.metrics) app.include_router(router, prefix="/api/v1") +pipeline_schema.mount_schema_documentation(app) def register_exceptions(): diff --git a/backend/capellacollab/alembic/versions/e3f1006f6b49_add_plugins_table.py b/backend/capellacollab/alembic/versions/e3f1006f6b49_add_plugins_table.py new file mode 100644 index 000000000..c964b4901 --- /dev/null +++ b/backend/capellacollab/alembic/versions/e3f1006f6b49_add_plugins_table.py @@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors +# SPDX-License-Identifier: Apache-2.0 + +"""Add plugins table + +Revision ID: e3f1006f6b49 +Revises: d0cbf2813066 +Create Date: 2023-05-26 11:56:13.928534 + +""" +import sqlalchemy as sa +from alembic import op +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = "e3f1006f6b49" +down_revision = "ac0e6e0f77ee" +branch_labels = None +depends_on = None + + +def upgrade(): + op.create_table( + "plugins", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("username", sa.String(), nullable=True), + sa.Column("password", sa.String(), nullable=True), + sa.Column("remote", sa.String(), nullable=False), + sa.Column( + "content", postgresql.JSONB(astext_type=sa.Text()), nullable=True + ), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index(op.f("ix_plugins_id"), "plugins", ["id"], unique=True) diff --git a/backend/capellacollab/core/database/__init__.py b/backend/capellacollab/core/database/__init__.py index e88ae49e4..3d47538cf 100644 --- a/backend/capellacollab/core/database/__init__.py +++ b/backend/capellacollab/core/database/__init__.py @@ -18,7 +18,10 @@ class Base(orm.DeclarativeBase): - type_annotation_map = {dict[str, str]: postgresql.JSONB} + type_annotation_map = { + dict[str, str]: postgresql.JSONB, + dict[str, t.Any]: postgresql.JSONB, + } ### SQL MODELS ARE IMPORTED HERE ### diff --git a/backend/capellacollab/core/database/models.py b/backend/capellacollab/core/database/models.py index 0b85bc619..a51d2729a 100644 --- a/backend/capellacollab/core/database/models.py +++ b/backend/capellacollab/core/database/models.py @@ -5,12 +5,13 @@ # These import statements of the models are required and should not be removed! (SQLAlchemy will not load the models otherwise) import capellacollab.notices.models +import capellacollab.plugins.models import capellacollab.projects.models -import capellacollab.projects.toolmodels.backups.models -import capellacollab.projects.toolmodels.backups.runs.models import capellacollab.projects.toolmodels.models import capellacollab.projects.toolmodels.modelsources.git.models import capellacollab.projects.toolmodels.modelsources.t4c.models +import capellacollab.projects.toolmodels.pipelines.models +import capellacollab.projects.toolmodels.pipelines.runs.models import capellacollab.projects.toolmodels.restrictions.models import capellacollab.projects.users.models import capellacollab.sessions.models diff --git a/backend/capellacollab/health/models.py b/backend/capellacollab/health/models.py index 980fa951f..211141927 100644 --- a/backend/capellacollab/health/models.py +++ b/backend/capellacollab/health/models.py @@ -6,12 +6,12 @@ import pydantic -from capellacollab.projects.toolmodels.backups.runs import ( - models as pipeline_run_models, -) from capellacollab.projects.toolmodels.modelsources.git import ( models as git_models, ) +from capellacollab.projects.toolmodels.pipelines.runs import ( + models as pipeline_run_models, +) class StatusResponse(pydantic.BaseModel): diff --git a/backend/capellacollab/health/routes.py b/backend/capellacollab/health/routes.py index 746f1a0bc..f60ca332a 100644 --- a/backend/capellacollab/health/routes.py +++ b/backend/capellacollab/health/routes.py @@ -11,11 +11,11 @@ import capellacollab.core.authentication.injectables as auth_injectables import capellacollab.core.logging as core_logging import capellacollab.projects.crud as projects_crud -import capellacollab.projects.toolmodels.backups.validation as pipelines_validation import capellacollab.projects.toolmodels.crud as toolmodels_crud import capellacollab.projects.toolmodels.diagrams.validation as diagrams_validation import capellacollab.projects.toolmodels.modelbadge.validation as modelbadge_validation import capellacollab.projects.toolmodels.modelsources.git.validation as git_validation +import capellacollab.projects.toolmodels.pipelines.validation as pipelines_validation import capellacollab.projects.toolmodels.validation as toolmodels_validation import capellacollab.projects.validation as projects_validation import capellacollab.users.models as users_models diff --git a/backend/capellacollab/projects/toolmodels/backups/__init__.py b/backend/capellacollab/plugins/__init__.py similarity index 100% rename from backend/capellacollab/projects/toolmodels/backups/__init__.py rename to backend/capellacollab/plugins/__init__.py diff --git a/backend/capellacollab/plugins/crud.py b/backend/capellacollab/plugins/crud.py new file mode 100644 index 000000000..8eaee3546 --- /dev/null +++ b/backend/capellacollab/plugins/crud.py @@ -0,0 +1,62 @@ +# SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors +# SPDX-License-Identifier: Apache-2.0 + + +from collections import abc + +import sqlalchemy as sa +from sqlalchemy import orm + +from . import models + + +def get_plugins(db: orm.Session) -> abc.Sequence[models.DatabasePlugin]: + return db.execute(sa.select(models.DatabasePlugin)).scalars().all() + + +def get_plugin_by_id( + db: orm.Session, plugin_id: int +) -> models.DatabasePlugin | None: + return db.execute( + sa.select(models.DatabasePlugin).where( + models.DatabasePlugin.id == plugin_id + ) + ).scalar_one_or_none() + + +def create_plugin( + db: orm.Session, + remote: str, + username: str | None, + password: str | None, + content: dict | None, +) -> models.DatabasePlugin: + plugin = models.DatabasePlugin( + remote=remote, username=username, password=password, content=content + ) + db.add(plugin) + db.commit() + return plugin + + +def update_plugin( + db: orm.Session, + plugin: models.DatabasePlugin, + patch_plugin: models.PatchPlugin, + content: str, +) -> models.DatabasePlugin: + if patch_plugin.username: + plugin.username = patch_plugin.username + if patch_plugin.password: + plugin.password = patch_plugin.password + if patch_plugin.remote: + plugin.remote = patch_plugin.remote + if content: + plugin.content = content + db.commit() + return plugin + + +def delete_plugin(db: orm.Session, plugin: models.DatabasePlugin) -> None: + db.delete(plugin) + db.commit() diff --git a/backend/capellacollab/plugins/injectables.py b/backend/capellacollab/plugins/injectables.py new file mode 100644 index 000000000..a2b594fc6 --- /dev/null +++ b/backend/capellacollab/plugins/injectables.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors +# SPDX-License-Identifier: Apache-2.0 + +from fastapi import Depends, HTTPException +from sqlalchemy.orm import Session + +from capellacollab.core import database + +from . import crud, models + + +def get_existing_plugin( + plugin_id: int, db: Session = Depends(database.get_db) +) -> models.DatabasePlugin: + if plugin := crud.get_plugin_by_id(db, plugin_id): + return plugin + + raise HTTPException( + 404, + { + "reason": f"The plugin with the id {plugin_id} was not found.", + }, + ) diff --git a/backend/capellacollab/plugins/models.py b/backend/capellacollab/plugins/models.py new file mode 100644 index 000000000..cc9a920e2 --- /dev/null +++ b/backend/capellacollab/plugins/models.py @@ -0,0 +1,267 @@ +# SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +import typing as t + +import croniter +import pydantic +from sqlalchemy import orm + +from capellacollab.core import database + + +class CreatePlugin(pydantic.BaseModel): + model_config = pydantic.ConfigDict(from_attributes=True) + + username: str | None + password: str | None + remote: str + + +class PatchPlugin(pydantic.BaseModel): + model_config = pydantic.ConfigDict(from_attributes=True) + + username: str | None = None + password: str | None = None + remote: str | None = None + + +class PluginMetadata(pydantic.BaseModel): + id: str = pydantic.Field( + title="Plugin identifier", + description="Unique identifier of the plugin.", + examples=["hello-world", "test-plugin"], + min_length=1, + max_length=50, + ) + display_name: str | None = pydantic.Field( + title="Display name of the plugin for the frontend", + description="Display name for the plugin. The name is used in the frontend to display the plugin. If ommitted, the id is used instead.", + examples=["Hello world", "A to B synchronization"], + alias="displayName", + min_length=0, + max_length=200, + ) + description: str | None = pydantic.Field( + title="Description of the plugin", + description=( + "Description of the plugin. " + "The description should explain the purpose of the plugin. " + "The user should be able to understand what the plugin does by reading the description." + ), + examples=[ + "This plugin runs the hello-world Docker container.", + "Synchronize the content from A to B.", + ], + min_length=0, + max_length=500, + ) + + +class PluginTrigger(pydantic.BaseModel): + cron: str = pydantic.Field( + title="Cron expression", + description="If provided and enabled, the pipelines are triggered automatically according to the cron expression.", + examples=["0 0 * * *", "*/5 * * * *"], + min_length=0, + max_length=50, + ) + manual: bool = pydantic.Field( + title="Manual trigger", + description="If true and enabled, the plugin can be triggered manually by the user.", + ) + + @pydantic.field_validator("cron") + @classmethod + def validate_cron_expression(cls, value): + try: + # Attempt to create a croniter object with the expression + croniter.croniter(value) + except (ValueError, croniter.CroniterBadCronError): + raise ValueError("Invalid cron expression") + return value + + +class T4CPluginInputMapping(pydantic.BaseModel): + host: str = pydantic.Field( + title="Host of the TeamForCapella server", + description=( + "Host of the TeamForCapella server." + "The host can be a hostname or an IP address," + "e.g. `t4c.example.com` or `prod-6-0-0-server-internal.t4c-server.svc.cluster.local`" + ), + examples=["T4C_REPO_HOST", "T4C_SERVER_HOST"], + ) + repository_port: str = pydantic.Field( + title="Repository port of the TeamForCapella server", + alias="repositoryPort", + description=( + "Repository port of the TeamForCapella server." + "The default port is 2036." + ), + examples=["T4C_REPO_PORT"], + ) + cdo_port: str = pydantic.Field( + title="CDO port of the TeamForCapella server", + alias="cdoPort", + description=( + "CDO port of the TeamForCapella server." + "The default port is 12036." + "The CDO port is disbabled by default since TeamForCapella version 6.0.0." + ), + examples=["T4C_CDO_PORT"], + ) + repository_name: str = pydantic.Field( + title="Name of the TeamForCapella repository", + alias="repositoryName", + description=( + "Name of the TeamForCapella repository, " + "e.g. `repository_without_authentication` or `repoCapella`." + ), + examples=["T4C_REPO_NAME", "T4C_REPOSITORY_NAME"], + ) + project_name: str = pydantic.Field( + title="Name of the TeamForCapella project", + alias="projectName", + description=( + "Name of the TeamForCapella project, e.g. `test-project`. " + "Should match the name of the `.project` file in Capella." + ), + examples=["T4C_PROJECT_NAME"], + ) + repository_username: str = pydantic.Field( + title="Username for the TeamForCapella repository", + alias="repositoryUsername", + description=( + "Username of the TeamForCapella repository user. " + "A technical user will be auto-generated for the repository." + ), + examples=["T4C_USERNAME"], + ) + repository_password: str = pydantic.Field( + title="Password for the TeamForCapella repository", + alias="repositoryPassword", + description=( + "Password of the TeamForCapella repository user. " + "A technical user will be auto-generated for the repository." + ), + examples=["T4C_PASSWORD"], + ) + + +class GitPluginInputMapping(pydantic.BaseModel): + url: str = pydantic.Field( + title="HTTP URL of the Git repository", + description=( + "HTTP(S) URL of the Git repository, e.g. `https://github.com/DSD-DBS/capella-collab-manager.git`" + ), + examples=["GIT_URL", "GIT_REPO_URL"], + ) + username: str = pydantic.Field( + title="Username of the Git repository", + description="Username to authenticate against the Git repository", + examples=["GIT_USERNAME"], + ) + password: str = pydantic.Field( + title="Password of the Git repository", + description="Password to authenticate against the Git repository", + examples=["GIT_PASSWORD"], + ) + revision: str = pydantic.Field( + title="Revision of the Git repository", + description="Revision of the Git repository", + examples=["GIT_REPO_BRANCH", "GIT_REPO_REVISION", "GIT_REVISION"], + ) + + +class GitPluginInput(pydantic.BaseModel): + description: str = pydantic.Field( + title="Description", + description=( + "Description of the input. " + "Will be displayed in the Collaboration Manager frontend before the Git repository selection." + ), + examples=[ + "Select the Git repository, which is injected into the pipeline:" + ], + ) + type: t.Literal["git"] = pydantic.Field( + title="Used input type", + description="Use Git as input type.", + ) + mapping: GitPluginInputMapping = pydantic.Field( + title="Mapping of Git repository values from the Capella Collaboration manager database to environment variables.", + description=( + "Mapping of Git repository values to environment variables. " + "The values are mapped to the specificed environment variables. " + "The pipeline job can read the values from the environment variables." + ), + ) + + +class T4CPluginInput(pydantic.BaseModel): + description: str = pydantic.Field( + title="Description", + description=( + "Description of the input. " + "Will be displayed in the Collaboration Manager frontend before the TeamForCapella server/repository selection." + ), + examples=[ + "Select the TeamForCapella server, which is injected into the pipeline:" + ], + ) + type: t.Literal["t4c"] = pydantic.Field( + title="Used input type", + description="Use TeamForCapella as input type.", + ) + mapping: T4CPluginInputMapping = pydantic.Field( + title="Mapping of TeamForCapella server values from the Capella Collaboration manager database to environment variables.", + description=( + "Mapping of TeamForCapella server values to environment variables. " + "The values are mapped to the specificed environment variables. " + "The pipeline job can read the values from the environment variables." + ), + ) + + +class PluginJob(pydantic.BaseModel): + image: str = pydantic.Field( + title="Docker image, including the Docker tag", + description="Must be a valid Docker image name. It can contain a tag. If no tag is provided, the `:latest` tag is used.", + examples=["hello-world:latest"], + ) + + +class PluginContent(pydantic.BaseModel): + metadata: PluginMetadata = pydantic.Field( + title="Plugin metadata", + description="Metadata of the plugin.", + ) + trigger: PluginTrigger = pydantic.Field( + title="Plugin trigger", + description="Defition of trigger rules for the plugin pipelines.", + ) + input: list[T4CPluginInput | GitPluginInput] + job: PluginJob = pydantic.Field( + title="Job definition", + description="Defition of the plugin job.", + ) + + +class Plugin(CreatePlugin): + id: int + content: PluginContent | None + + +class DatabasePlugin(database.Base): + __tablename__ = "plugins" + + id: orm.Mapped[int] = orm.mapped_column( + unique=True, primary_key=True, index=True + ) + username: orm.Mapped[str | None] + password: orm.Mapped[str | None] + remote: orm.Mapped[str] + content: orm.Mapped[dict[str, t.Any] | None] diff --git a/backend/capellacollab/plugins/routes.py b/backend/capellacollab/plugins/routes.py new file mode 100644 index 000000000..4d1472611 --- /dev/null +++ b/backend/capellacollab/plugins/routes.py @@ -0,0 +1,157 @@ +# SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors +# SPDX-License-Identifier: Apache-2.0 + + +import logging +import typing as t + +import fastapi +import requests +import yaml +from requests import auth +from sqlalchemy.orm import Session + +from capellacollab.core import database +from capellacollab.core.authentication import injectables as auth_injectables +from capellacollab.users import models as user_models + +from . import crud, injectables, models, schema + +logger = logging.getLogger(__name__) +schema_router = fastapi.APIRouter() +router = fastapi.APIRouter( + dependencies=[ + fastapi.Depends( + auth_injectables.RoleVerification( + required_role=user_models.Role.USER + ) + ) + ] +) + + +@router.get( + "", + response_model=list[models.Plugin], +) +def get_plugins( + db: Session = fastapi.Depends(database.get_db), +) -> list[models.Plugin]: + return [ + models.Plugin.model_validate(plugin) for plugin in crud.get_plugins(db) + ] + + +@router.get( + "/{plugin_id}", + response_model=models.Plugin, +) +def get_plugin_by_id( + plugin: models.DatabasePlugin = fastapi.Depends( + injectables.get_existing_plugin + ), +) -> models.DatabasePlugin: + return plugin + + +@router.get( + "/{plugin_id}/refresh", + response_model=list[models.Plugin], +) +def refresh_plugins( + db: Session = fastapi.Depends(database.get_db), + plugin: models.DatabasePlugin = fastapi.Depends( + injectables.get_existing_plugin + ), +): + plugin.content = fetch_content( + plugin.remote, plugin.username, plugin.password + ) + db.commit() + + +@router.post("/peek-plugin-content", response_model=models.Plugin) +def fetch_plugin_content(plugin: models.CreatePlugin) -> models.Plugin: + content = fetch_content(plugin.remote, plugin.username, plugin.password) + return models.Plugin( + id=0, + remote=plugin.remote, + username=plugin.username, + password=plugin.password, + content=content, + ) + + +def fetch_content( + url: str, username: str | None, password: str | None +) -> dict[str, t.Any]: + basic_auth = None + if username and password: + basic_auth = auth.HTTPBasicAuth(username=username, password=password) + + response = requests.get(url, auth=basic_auth, timeout=2) + response.raise_for_status() + return yaml.safe_load(response.content.decode()) + + +@router.patch( + "/{plugin_id}", + response_model=models.Plugin, + tags=["Plugins"], +) +def update_plugin( + body: models.PatchPlugin, + plugin: models.DatabasePlugin = fastapi.Depends( + injectables.get_existing_plugin + ), + db: Session = fastapi.Depends(database.get_db), +) -> models.DatabasePlugin: + content = fetch_content(body.remote, body.username, body.password) + return crud.update_plugin(db, plugin, body, content) + + +@router.post( + "", + response_model=models.Plugin, + dependencies=[ + fastapi.Depends( + auth_injectables.RoleVerification( + required_role=user_models.Role.ADMIN + ) + ) + ], + tags=["Plugins"], +) +def create_plugin( + body: models.CreatePlugin, + db: Session = fastapi.Depends(database.get_db), +) -> models.Plugin: + content = fetch_content(body.remote, body.username, body.password) + return models.Plugin.model_validate( + crud.create_plugin( + db, + remote=body.remote, + username=body.username, + password=body.password, + content=content, + ) + ) + + +@router.delete( + "/{plugin_id}", + status_code=204, + tags=["Plugins"], +) +def delete_plugin( + plugin: models.DatabasePlugin = fastapi.Depends( + injectables.get_existing_plugin + ), + db: Session = fastapi.Depends(database.get_db), +) -> None: + crud.delete_plugin(db, plugin) + + +@schema_router.get("") +def get_plugin_schema() -> dict[str, t.Any]: + return schema.get_plugin_schema() diff --git a/backend/capellacollab/plugins/schema.py b/backend/capellacollab/plugins/schema.py new file mode 100644 index 000000000..90420a67c --- /dev/null +++ b/backend/capellacollab/plugins/schema.py @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors +# SPDX-License-Identifier: Apache-2.0 + +import io +import json +import pathlib +import tempfile +import typing as t + +import fastapi +from fastapi import staticfiles +from json_schema_for_humans import generate as json_schema + +from . import models + +documentation_directory = tempfile.TemporaryDirectory() +documentation_path = pathlib.Path(documentation_directory.name) + + +def get_plugin_schema_as_json() -> str: + return json.dumps(get_plugin_schema()) + + +def get_plugin_schema() -> dict[str, t.Any]: + return models.PluginContent.model_json_schema() + + +def generate_schema_documentation(): + with tempfile.NamedTemporaryFile( + mode="w+", encoding="utf-8" + ) as schema_file: + schema_file.write(get_plugin_schema_as_json()) + schema_file.seek(0) + json_schema.generate_from_filename( + schema_file.name, + result_file_name=str(documentation_path / "index.html"), + ) + + +def mount_schema_documentation(app: fastapi.FastAPI): + app.mount( + "/docs/plugin-schema", + staticfiles.StaticFiles(directory=documentation_path, html=True), + name="plugin-schema-docs", + ) + + +def cleanup_documentation_directory(): + documentation_directory.cleanup() diff --git a/backend/capellacollab/projects/routes.py b/backend/capellacollab/projects/routes.py index e46a16d8f..25063a3d0 100644 --- a/backend/capellacollab/projects/routes.py +++ b/backend/capellacollab/projects/routes.py @@ -15,9 +15,11 @@ from capellacollab.projects import injectables as projects_injectables from capellacollab.projects.events import routes as projects_events_routes from capellacollab.projects.toolmodels import routes as toolmodels_routes -from capellacollab.projects.toolmodels.backups import core as backups_core -from capellacollab.projects.toolmodels.backups import crud as backups_crud -from capellacollab.projects.toolmodels.backups import models as backups_models +from capellacollab.projects.toolmodels.pipelines import core as backups_core +from capellacollab.projects.toolmodels.pipelines import crud as backups_crud +from capellacollab.projects.toolmodels.pipelines import ( + models as backups_models, +) from capellacollab.projects.users import crud as projects_users_crud from capellacollab.projects.users import models as projects_users_models from capellacollab.projects.users import routes as projects_users_routes @@ -217,7 +219,6 @@ def _delete_all_pipelines_for_project( router.include_router( toolmodels_routes.router, prefix="/{project_slug}/models", - tags=["Projects - Models"], ) router.include_router( session_routes.project_router, diff --git a/backend/capellacollab/projects/toolmodels/modelsources/git/routes.py b/backend/capellacollab/projects/toolmodels/modelsources/git/routes.py index 519317307..003980f16 100644 --- a/backend/capellacollab/projects/toolmodels/modelsources/git/routes.py +++ b/backend/capellacollab/projects/toolmodels/modelsources/git/routes.py @@ -15,7 +15,7 @@ injectables as toolmodels_injectables, ) from capellacollab.projects.toolmodels import models as toolmodels_models -from capellacollab.projects.toolmodels.backups import crud as backups_crud +from capellacollab.projects.toolmodels.pipelines import crud as backups_crud from capellacollab.projects.users import models as projects_users_models from capellacollab.settings.modelsources.git import core as git_core from capellacollab.settings.modelsources.git import crud as git_crud diff --git a/backend/capellacollab/projects/toolmodels/modelsources/t4c/routes.py b/backend/capellacollab/projects/toolmodels/modelsources/t4c/routes.py index 916bbd0bb..c5cca018f 100644 --- a/backend/capellacollab/projects/toolmodels/modelsources/t4c/routes.py +++ b/backend/capellacollab/projects/toolmodels/modelsources/t4c/routes.py @@ -13,7 +13,7 @@ injectables as toolmodels_injectables, ) from capellacollab.projects.toolmodels import models as toolmodels_models -from capellacollab.projects.toolmodels.backups import crud as backups_crud +from capellacollab.projects.toolmodels.pipelines import crud as backups_crud from capellacollab.projects.users import models as projects_users_models from capellacollab.settings.modelsources.t4c import ( injectables as settings_t4c_injecatbles, diff --git a/backend/capellacollab/projects/toolmodels/backups/runs/__init__.py b/backend/capellacollab/projects/toolmodels/pipelines/__init__.py similarity index 100% rename from backend/capellacollab/projects/toolmodels/backups/runs/__init__.py rename to backend/capellacollab/projects/toolmodels/pipelines/__init__.py diff --git a/backend/capellacollab/projects/toolmodels/backups/core.py b/backend/capellacollab/projects/toolmodels/pipelines/core.py similarity index 97% rename from backend/capellacollab/projects/toolmodels/backups/core.py rename to backend/capellacollab/projects/toolmodels/pipelines/core.py index f58068bde..4efa69876 100644 --- a/backend/capellacollab/projects/toolmodels/backups/core.py +++ b/backend/capellacollab/projects/toolmodels/pipelines/core.py @@ -24,6 +24,10 @@ log = logging.getLogger(__name__) +def derive_environment_from_input() -> dict[str, str]: + return {} + + def get_environment( git_model: git_models.DatabaseGitModel, t4c_model: t4c_models.DatabaseT4CModel, diff --git a/backend/capellacollab/projects/toolmodels/backups/crud.py b/backend/capellacollab/projects/toolmodels/pipelines/crud.py similarity index 92% rename from backend/capellacollab/projects/toolmodels/backups/crud.py rename to backend/capellacollab/projects/toolmodels/pipelines/crud.py index c50c0d757..6cbf230c1 100644 --- a/backend/capellacollab/projects/toolmodels/backups/crud.py +++ b/backend/capellacollab/projects/toolmodels/pipelines/crud.py @@ -61,7 +61,7 @@ def get_pipelines_for_git_model( return ( db.execute( sa.select(models.DatabaseBackup).where( - models.DatabaseBackup.git_model_id == model.id + models.DatabaseBackup.git_model_id == model.id # type: ignore # FIXME: git_model_id doesn't exist anymore ) ) .scalars() @@ -75,7 +75,7 @@ def get_pipelines_for_t4c_model( return ( db.execute( sa.select(models.DatabaseBackup).where( - models.DatabaseBackup.t4c_model_id == t4c_model.id + models.DatabaseBackup.t4c_model_id == t4c_model.id # type: ignore # FIXME: git_model_id doesn't exist anymore ) ) .scalars() diff --git a/backend/capellacollab/projects/toolmodels/backups/exceptions.py b/backend/capellacollab/projects/toolmodels/pipelines/exceptions.py similarity index 100% rename from backend/capellacollab/projects/toolmodels/backups/exceptions.py rename to backend/capellacollab/projects/toolmodels/pipelines/exceptions.py diff --git a/backend/capellacollab/projects/toolmodels/backups/injectables.py b/backend/capellacollab/projects/toolmodels/pipelines/injectables.py similarity index 100% rename from backend/capellacollab/projects/toolmodels/backups/injectables.py rename to backend/capellacollab/projects/toolmodels/pipelines/injectables.py diff --git a/backend/capellacollab/projects/toolmodels/backups/models.py b/backend/capellacollab/projects/toolmodels/pipelines/models.py similarity index 83% rename from backend/capellacollab/projects/toolmodels/backups/models.py rename to backend/capellacollab/projects/toolmodels/pipelines/models.py index ef784da68..b486c2fd2 100644 --- a/backend/capellacollab/projects/toolmodels/backups/models.py +++ b/backend/capellacollab/projects/toolmodels/pipelines/models.py @@ -60,18 +60,8 @@ class DatabaseBackup(database.Base): t4c_username: orm.Mapped[str] t4c_password: orm.Mapped[str] - include_commit_history: orm.Mapped[bool] run_nightly: orm.Mapped[bool] - - git_model_id: orm.Mapped[int] = orm.mapped_column( - sa.ForeignKey("git_models.id") - ) - git_model: orm.Mapped["DatabaseGitModel"] = orm.relationship() - - t4c_model_id: orm.Mapped[int] = orm.mapped_column( - sa.ForeignKey("t4c_models.id") - ) - t4c_model: orm.Mapped["DatabaseT4CModel"] = orm.relationship() + content: orm.Mapped[dict[str, t.Any]] model_id: orm.Mapped[int] = orm.mapped_column(sa.ForeignKey("models.id")) model: orm.Mapped["DatabaseCapellaModel"] = orm.relationship() diff --git a/backend/capellacollab/projects/toolmodels/backups/routes.py b/backend/capellacollab/projects/toolmodels/pipelines/routes.py similarity index 100% rename from backend/capellacollab/projects/toolmodels/backups/routes.py rename to backend/capellacollab/projects/toolmodels/pipelines/routes.py diff --git a/backend/capellacollab/projects/toolmodels/pipelines/runs/__init__.py b/backend/capellacollab/projects/toolmodels/pipelines/runs/__init__.py new file mode 100644 index 000000000..677cdfe33 --- /dev/null +++ b/backend/capellacollab/projects/toolmodels/pipelines/runs/__init__.py @@ -0,0 +1,2 @@ +# SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors +# SPDX-License-Identifier: Apache-2.0 diff --git a/backend/capellacollab/projects/toolmodels/backups/runs/crud.py b/backend/capellacollab/projects/toolmodels/pipelines/runs/crud.py similarity index 100% rename from backend/capellacollab/projects/toolmodels/backups/runs/crud.py rename to backend/capellacollab/projects/toolmodels/pipelines/runs/crud.py diff --git a/backend/capellacollab/projects/toolmodels/backups/runs/helper.py b/backend/capellacollab/projects/toolmodels/pipelines/runs/helper.py similarity index 100% rename from backend/capellacollab/projects/toolmodels/backups/runs/helper.py rename to backend/capellacollab/projects/toolmodels/pipelines/runs/helper.py diff --git a/backend/capellacollab/projects/toolmodels/backups/runs/injectables.py b/backend/capellacollab/projects/toolmodels/pipelines/runs/injectables.py similarity index 89% rename from backend/capellacollab/projects/toolmodels/backups/runs/injectables.py rename to backend/capellacollab/projects/toolmodels/pipelines/runs/injectables.py index c75ea43dd..7a5576eb3 100644 --- a/backend/capellacollab/projects/toolmodels/backups/runs/injectables.py +++ b/backend/capellacollab/projects/toolmodels/pipelines/runs/injectables.py @@ -6,10 +6,12 @@ from sqlalchemy import orm from capellacollab.core import database -from capellacollab.projects.toolmodels.backups import ( +from capellacollab.projects.toolmodels.pipelines import ( injectables as backups_injectables, ) -from capellacollab.projects.toolmodels.backups import models as backups_models +from capellacollab.projects.toolmodels.pipelines import ( + models as backups_models, +) from . import crud, models diff --git a/backend/capellacollab/projects/toolmodels/backups/runs/interface.py b/backend/capellacollab/projects/toolmodels/pipelines/runs/interface.py similarity index 99% rename from backend/capellacollab/projects/toolmodels/backups/runs/interface.py rename to backend/capellacollab/projects/toolmodels/pipelines/runs/interface.py index 1f227250d..be24805a8 100644 --- a/backend/capellacollab/projects/toolmodels/backups/runs/interface.py +++ b/backend/capellacollab/projects/toolmodels/pipelines/runs/interface.py @@ -15,7 +15,7 @@ from capellacollab.projects.toolmodels import ( exceptions as toolmodels_exceptions, ) -from capellacollab.projects.toolmodels.backups import core as backups_core +from capellacollab.projects.toolmodels.pipelines import core as backups_core from capellacollab.sessions import operators from capellacollab.tools import crud as tools_crud diff --git a/backend/capellacollab/projects/toolmodels/backups/runs/models.py b/backend/capellacollab/projects/toolmodels/pipelines/runs/models.py similarity index 100% rename from backend/capellacollab/projects/toolmodels/backups/runs/models.py rename to backend/capellacollab/projects/toolmodels/pipelines/runs/models.py diff --git a/backend/capellacollab/projects/toolmodels/backups/runs/routes.py b/backend/capellacollab/projects/toolmodels/pipelines/runs/routes.py similarity index 100% rename from backend/capellacollab/projects/toolmodels/backups/runs/routes.py rename to backend/capellacollab/projects/toolmodels/pipelines/runs/routes.py diff --git a/backend/capellacollab/projects/toolmodels/backups/validation.py b/backend/capellacollab/projects/toolmodels/pipelines/validation.py similarity index 100% rename from backend/capellacollab/projects/toolmodels/backups/validation.py rename to backend/capellacollab/projects/toolmodels/pipelines/validation.py diff --git a/backend/capellacollab/projects/toolmodels/routes.py b/backend/capellacollab/projects/toolmodels/routes.py index 412b6a4ff..f5e3f156b 100644 --- a/backend/capellacollab/projects/toolmodels/routes.py +++ b/backend/capellacollab/projects/toolmodels/routes.py @@ -21,10 +21,10 @@ from capellacollab.users import models as users_models from . import crud, injectables, models, workspace -from .backups import routes as backups_routes from .diagrams import routes as diagrams_routes from .modelbadge import routes as complexity_badge_routes from .modelsources import routes as modelsources_routes +from .pipelines import routes as pipelines_routes from .restrictions import routes as restrictions_routes router = fastapi.APIRouter( @@ -299,9 +299,9 @@ def raise_if_model_exists_in_project( prefix="/{model_slug}/modelsources", ) router.include_router( - backups_routes.router, - prefix="/{model_slug}/backups/pipelines", - tags=["Projects - Models - Backups"], + pipelines_routes.router, + prefix="/{model_slug}/pipelines", + tags=["Projects - Models - Pipelines"], ) router.include_router( restrictions_routes.router, diff --git a/backend/capellacollab/routes.py b/backend/capellacollab/routes.py index adb726e41..78e41aa77 100644 --- a/backend/capellacollab/routes.py +++ b/backend/capellacollab/routes.py @@ -12,6 +12,7 @@ from capellacollab.core.authentication import responses as auth_responses from capellacollab.health import routes as health_routes from capellacollab.notices import routes as notices_routes +from capellacollab.plugins import routes as plugins_routes from capellacollab.projects import routes as projects_routes from capellacollab.sessions import routes as sessions_routes from capellacollab.settings import routes as settings_routes @@ -40,6 +41,18 @@ prefix="/projects", responses=auth_responses.AUTHENTICATION_RESPONSES, ) +router.include_router( + plugins_routes.router, + tags=["Plugins"], + prefix="/plugins", + responses=auth_responses.AUTHENTICATION_RESPONSES, +) +router.include_router( + plugins_routes.schema_router, + tags=["Plugins"], + prefix="/plugins-schema", + responses=auth_responses.AUTHENTICATION_RESPONSES, +) router.include_router( tools_routes.router, prefix="/tools", @@ -67,5 +80,5 @@ router.include_router( importlib.import_module(".routes", ep.module).router, prefix="/authentication", - tags=[ep.name], + tags=["Authentication"], ) diff --git a/backend/capellacollab/settings/routes.py b/backend/capellacollab/settings/routes.py index a012fb1fa..81a8330ba 100644 --- a/backend/capellacollab/settings/routes.py +++ b/backend/capellacollab/settings/routes.py @@ -24,5 +24,7 @@ prefix="/modelsources", ) router.include_router( - purevariants_routes.router, prefix="/integrations/pure-variants" + purevariants_routes.router, + tags=["Settings - Integrations"], + prefix="/integrations/pure-variants", ) diff --git a/backend/plugin_schema.yml b/backend/plugin_schema.yml new file mode 100644 index 000000000..0c6f9a524 --- /dev/null +++ b/backend/plugin_schema.yml @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors +# SPDX-License-Identifier: Apache-2.0 + +{"$defs": {"PluginMetadata": {"properties": {"id": {"description": "Unique identifier of the plugin.", "examples": ["hello-world", "test-plugin"], "maxLength": 50, "minLength": 1, "title": "Plugin identifier", "type": "string"}, "displayName": {"anyOf": [{"maxLength": 200, "minLength": 0, "type": "string"}, {"type": "null"}], "description": "Display name for the plugin. The name is used in the frontend to display the plugin. If ommitted, the id is used instead.", "examples": ["Hello world", "A to B synchronization"], "title": "Display name of the plugin for the frontend"}, "description": {"anyOf": [{"maxLength": 500, "minLength": 0, "type": "string"}, {"type": "null"}], "description": "Description of the plugin. The description should explain the purpose of the plugin. The user should be able to understand what the plugin does by reading the description.", "examples": ["This plugin runs the hello-world Docker container.", "Synchronize the content from A to B."], "title": "Description of the plugin"}}, "required": ["id", "displayName", "description"], "title": "PluginMetadata", "type": "object"}}, "properties": {"metadata": {"$ref": "#/$defs/PluginMetadata"}}, "required": ["metadata"], "title": "PluginContent", "type": "object"} diff --git a/backend/plugin_schema/plugin_schema.html b/backend/plugin_schema/plugin_schema.html new file mode 100644 index 000000000..25c44bbf8 --- /dev/null +++ b/backend/plugin_schema/plugin_schema.html @@ -0,0 +1,12 @@ + + + PluginContent

PluginContent

Type: object

Type: object

Type: string

Unique identifier of the plugin.

Must be at least 1 characters long

Must be at most 50 characters long


Examples:

"hello-world"
+
"test-plugin"
+


Display name for the plugin. The name is used in the frontend to display the plugin. If ommitted, the id is used instead.

Type: string

Must be at least 0 characters long

Must be at most 200 characters long

Type: null

Examples:

"Hello world"
+
"A to B synchronization"
+


Description of the plugin. The description should explain the purpose of the plugin. The user should be able to understand what the plugin does by reading the description.

Type: string

Must be at least 0 characters long

Must be at most 500 characters long

Type: null

Examples:

"This plugin runs the hello-world Docker container."
+
"Synchronize the content from A to B."
+
diff --git a/backend/plugin_schema/schema_doc.css b/backend/plugin_schema/schema_doc.css new file mode 100644 index 000000000..2b716a247 --- /dev/null +++ b/backend/plugin_schema/schema_doc.css @@ -0,0 +1,186 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +body { + font: 16px/1.5em "Overpass", "Open Sans", Helvetica, sans-serif; + color: #333; + font-weight: 300; + padding: 40px; +} + +.btn.btn-link { + font-size: 18px; + user-select: text; +} + +.jsfh-animated-property { + animation: eclair; + animation-iteration-count: 1; + animation-fill-mode: forwards; + animation-duration: .75s; + +} + +@keyframes eclair { + 0%,100% { + transform: scale(1); + } + 50% { + transform: scale(1.03); + } +} + +.btn.btn-primary { + margin: 10px; +} + +.btn.example-show.collapsed:before { + content: "show" +} + +.btn.example-show:before { + content: "hide" +} + +.description.collapse:not(.show) { + max-height: 100px !important; + overflow: hidden; + + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; +} + +.description.collapsing { + min-height: 100px !important; +} + +.collapse-description-link.collapsed:after { + content: '+ Read More'; +} + +.collapse-description-link:not(.collapsed):after { + content: '- Read Less'; +} + +.badge { + font-size: 100%; + margin-bottom: 0.5rem; + margin-top: 0.5rem; +} + +.badge.value-type { + font-size: 120%; + margin-right: 5px; + margin-bottom: 10px; +} + + +.badge.default-value { + font-size: 120%; + margin-left: 5px; + margin-bottom: 10px; +} + +.badge.restriction { + display: inline-block; +} + +.badge.required-property,.badge.deprecated-property,.badge.pattern-property,.badge.no-additional { + font-size: 100%; + margin-left: 10px; +} + +.accordion div.card:only-child { + border-bottom: 1px solid rgba(0, 0, 0, 0.125); +} + +.examples { + padding: 1rem !important; +} + +.examples pre { + margin-bottom: 0; +} + +.highlight.jumbotron { + padding: 1rem !important; +} + +.generated-by-footer { + margin-top: 1em; + text-align: right; +} + +/* From https://github.com/richleland/pygments-css/blob/master/friendly.css, see https://github.com/trentm/python-markdown2/wiki/fenced-code-blocks */ +.highlight { background: #e9ecef; } /* Changed from #f0f0f0 in the original style to be the same as bootstrap's jumbotron */ +.highlight .hll { background-color: #ffffcc } +.highlight .c { color: #60a0b0; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .ch { color: #60a0b0; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #007020 } /* Comment.Preproc */ +.highlight .cpf { color: #60a0b0; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0044DD } /* Generic.Traceback */ +.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #902000 } /* Keyword.Type */ +.highlight .m { color: #40a070 } /* Literal.Number */ +.highlight .s { color: #4070a0 } /* Literal.String */ +.highlight .na { color: #4070a0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ +.highlight .no { color: #60add5 } /* Name.Constant */ +.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #007020 } /* Name.Exception */ +.highlight .nf { color: #06287e } /* Name.Function */ +.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #bb60d5 } /* Name.Variable */ +.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mb { color: #40a070 } /* Literal.Number.Bin */ +.highlight .mf { color: #40a070 } /* Literal.Number.Float */ +.highlight .mh { color: #40a070 } /* Literal.Number.Hex */ +.highlight .mi { color: #40a070 } /* Literal.Number.Integer */ +.highlight .mo { color: #40a070 } /* Literal.Number.Oct */ +.highlight .sa { color: #4070a0 } /* Literal.String.Affix */ +.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ +.highlight .sc { color: #4070a0 } /* Literal.String.Char */ +.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ +.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4070a0 } /* Literal.String.Double */ +.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ +.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ +.highlight .sx { color: #c65d09 } /* Literal.String.Other */ +.highlight .sr { color: #235388 } /* Literal.String.Regex */ +.highlight .s1 { color: #4070a0 } /* Literal.String.Single */ +.highlight .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #06287e } /* Name.Function.Magic */ +.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ +.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ +.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ +.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ +.highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */ diff --git a/backend/plugin_schema/schema_doc.min.js b/backend/plugin_schema/schema_doc.min.js new file mode 100644 index 000000000..e37a5a5a6 --- /dev/null +++ b/backend/plugin_schema/schema_doc.min.js @@ -0,0 +1,6 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +$(document).on("click",'a[href^="#"]',function(event){event.preventDefault();history.pushState({},"",this.href)});function flashElement(elementId){myElement=document.getElementById(elementId);myElement.classList.add("jsfh-animated-property");setTimeout(function(){myElement.classList.remove("jsfh-animated-property")},1e3)}function setAnchor(anchorLinkDestination){history.pushState({},"",anchorLinkDestination)}function anchorOnLoad(){let linkTarget=decodeURIComponent(window.location.hash.split("?")[0].split("&")[0]);if(linkTarget[0]==="#"){linkTarget=linkTarget.substr(1)}if(linkTarget.length>0){anchorLink(linkTarget)}}function anchorLink(linkTarget){const target=$("#"+linkTarget);target.parents().addBack().filter(".collapse:not(.show), .tab-pane, [role='tab']").each(function(index){if($(this).hasClass("collapse")){$(this).collapse("show")}else if($(this).hasClass("tab-pane")){const tabToShow=$("a[href='#"+$(this).attr("id")+"']");if(tabToShow){tabToShow.tab("show")}}else if($(this).attr("role")==="tab"){$(this).tab("show")}});setTimeout(function(){let targetElement=document.getElementById(linkTarget);if(targetElement){targetElement.scrollIntoView({block:"center",behavior:"smooth"});setTimeout(function(){flashElement(linkTarget)},500)}},1e3)} diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 133911f23..48b7ff217 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -45,6 +45,7 @@ dependencies = [ "aiohttp", "argon2-cffi", "typer", + "croniter", ] [project.urls] @@ -133,6 +134,8 @@ module = [ "jwt.*", "argon2.*", "websocket.*" + "croniter.*", + "json_schema_for_humans.*", ] ignore_missing_imports = true diff --git a/backend/tests/data/mbse-works-plugins/hello-world.yml b/backend/tests/data/mbse-works-plugins/hello-world.yml new file mode 100644 index 000000000..3964558f1 --- /dev/null +++ b/backend/tests/data/mbse-works-plugins/hello-world.yml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors +# SPDX-License-Identifier: Apache-2.0 + +metadata: + id: hello-world + displayName: Hello world + description: | + Run the "Hello world" Docker container. + +trigger: + manual: true + +job: + image: hello-world diff --git a/backend/tests/data/mbse-works-plugins/t4c-to-git.yml b/backend/tests/data/mbse-works-plugins/t4c-to-git.yml new file mode 100644 index 000000000..a7de6aa78 --- /dev/null +++ b/backend/tests/data/mbse-works-plugins/t4c-to-git.yml @@ -0,0 +1,52 @@ +# SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors +# SPDX-License-Identifier: Apache-2.0 + +metadata: + id: t4c-to-git + displayName: T4C to Git synchronization + description: | + Synchronize the content from a T4C repository project to a Git repository. + +trigger: + cron: "0 3 * * 2-6" + manual: true + +input: + - type: git + description: Select the Git repository to synchronize to. + mapping: + url: GIT_REPO_URL + username: GIT_USERNAME + password: GIT_PASSWORD + revision: GIT_REPO_BRANCH + - type: t4c + description: Select the T4C repository project to synchronize from. + mapping: + host: T4C_REPO_HOST + repositoryPort: T4C_REPO_PORT + cdoPort: T4C_CDO_PORT + repositoryName: T4C_REPO_NAME + projectName: T4C_PROJECT_NAME + repositoryUsername: T4C_USERNAME + repositoryPassword: T4C_PASSWORD + - type: environment + variables: + - key: LOG_LEVEL + type: dropdown + values: ["DEBUG", "INFO", "WARN", "ERROR"] + displayName: Log level + description: "Specify the log level of the script:" + default: INFO + - key: INCLUDE_COMMIT_HISTORY + type: boolean + displayName: Include commit history + description: > + Do you want to include the commit history? + When the commit history is included, the pipeline is significantly slower. + It can take multiple hours to synchronize a project with a long commit history. + default: false + +job: + image: $DOCKER_REGISTRY/t4c/client/backup + cmd: + - backup diff --git a/backend/tests/projects/toolmodels/pipelines/conftest.py b/backend/tests/projects/toolmodels/pipelines/conftest.py index 0dc9e19ea..f4b34f380 100644 --- a/backend/tests/projects/toolmodels/pipelines/conftest.py +++ b/backend/tests/projects/toolmodels/pipelines/conftest.py @@ -5,16 +5,16 @@ from sqlalchemy import orm from capellacollab.projects.toolmodels import models as toolmodels_models -from capellacollab.projects.toolmodels.backups import crud as pipelines_crud -from capellacollab.projects.toolmodels.backups import ( - models as pipelines_models, -) from capellacollab.projects.toolmodels.modelsources.git import ( models as git_models, ) from capellacollab.projects.toolmodels.modelsources.t4c import ( models as t4c_models, ) +from capellacollab.projects.toolmodels.pipelines import crud as pipelines_crud +from capellacollab.projects.toolmodels.pipelines import ( + models as pipelines_models, +) @pytest.fixture(name="run_nightly", params=[True, False]) diff --git a/backend/tests/projects/toolmodels/pipelines/pipeline-runs/conftest.py b/backend/tests/projects/toolmodels/pipelines/pipeline-runs/conftest.py index 9f6c6452a..24e306672 100644 --- a/backend/tests/projects/toolmodels/pipelines/pipeline-runs/conftest.py +++ b/backend/tests/projects/toolmodels/pipelines/pipeline-runs/conftest.py @@ -6,9 +6,9 @@ import pytest from sqlalchemy import orm -import capellacollab.projects.toolmodels.backups.models as pipeline_models -import capellacollab.projects.toolmodels.backups.runs.crud as pipeline_runs_crud -import capellacollab.projects.toolmodels.backups.runs.models as pipeline_runs_models +import capellacollab.projects.toolmodels.pipelines.models as pipeline_models +import capellacollab.projects.toolmodels.pipelines.runs.crud as pipeline_runs_crud +import capellacollab.projects.toolmodels.pipelines.runs.models as pipeline_runs_models import capellacollab.users.models as users_models diff --git a/backend/tests/projects/toolmodels/pipelines/pipeline-runs/test_pipeline_runs.py b/backend/tests/projects/toolmodels/pipelines/pipeline-runs/test_pipeline_runs.py index 326c595c8..77e20bb61 100644 --- a/backend/tests/projects/toolmodels/pipelines/pipeline-runs/test_pipeline_runs.py +++ b/backend/tests/projects/toolmodels/pipelines/pipeline-runs/test_pipeline_runs.py @@ -10,16 +10,16 @@ from sqlalchemy import orm import capellacollab.projects.models as project_models -import capellacollab.projects.toolmodels.backups.models as pipelines_models -import capellacollab.projects.toolmodels.backups.runs.crud as pipeline_runs_crud -import capellacollab.projects.toolmodels.backups.runs.models as pipeline_runs_models import capellacollab.projects.toolmodels.models as toolmodels_models +import capellacollab.projects.toolmodels.pipelines.models as pipelines_models +import capellacollab.projects.toolmodels.pipelines.runs.crud as pipeline_runs_crud +import capellacollab.projects.toolmodels.pipelines.runs.models as pipeline_runs_models from capellacollab.__main__ import app from capellacollab.core.logging import loki -from capellacollab.projects.toolmodels.backups.runs import ( +from capellacollab.projects.toolmodels.pipelines.runs import ( injectables as runs_injectables, ) -from capellacollab.projects.toolmodels.backups.runs import ( +from capellacollab.projects.toolmodels.pipelines.runs import ( models as runs_models, ) from capellacollab.users import crud as users_crud @@ -58,7 +58,7 @@ def test_create_pipeline_run( pipeline: pipelines_models.DatabaseBackup, ): response = client.post( - f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/backups/pipelines/{pipeline.id}/runs", + f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/pipelines/{pipeline.id}/runs", json={}, ) @@ -77,7 +77,7 @@ def test_create_pipeline_run_with_custom_environment( pipeline: pipelines_models.DatabaseBackup, ): response = client.post( - f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/backups/pipelines/{pipeline.id}/runs", + f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/pipelines/{pipeline.id}/runs", json={ "include_commit_history": True, }, @@ -95,7 +95,7 @@ def test_get_pipeline_runs( pipeline_run: pipeline_runs_models.DatabasePipelineRun, ): response = client.get( - f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/backups/pipelines/{pipeline.id}/runs?page=1&size=50", + f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/pipelines/{pipeline.id}/runs?page=1&size=50", ) assert response.status_code == 200 @@ -111,7 +111,7 @@ def test_get_pipeline_run( pipeline_run: pipeline_runs_models.DatabasePipelineRun, ): response = client.get( - f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/backups/pipelines/{pipeline.id}/runs/{pipeline_run.id}", + f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/pipelines/{pipeline.id}/runs/{pipeline_run.id}", ) assert response.status_code == 200 @@ -127,7 +127,7 @@ def test_get_events( pipeline_run: pipeline_runs_models.DatabasePipelineRun, ): response = client.get( - f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/backups/pipelines/{pipeline.id}/runs/{pipeline_run.id}/events", + f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/pipelines/{pipeline.id}/runs/{pipeline_run.id}/events", ) assert response.status_code == 200 assert b"test3" in response.content @@ -142,7 +142,7 @@ def def_get_logs( pipeline_run: pipeline_runs_models.DatabasePipelineRun, ): response = client.get( - f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/backups/pipelines/{pipeline.id}/runs/{pipeline_run.id}/logs", + f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/pipelines/{pipeline.id}/runs/{pipeline_run.id}/logs", ) assert response.status_code == 200 @@ -210,7 +210,7 @@ def test_mask_logs( ] response = client.get( - "/api/v1/projects/1/models/1/backups/pipelines/1/runs/1/logs" + "/api/v1/projects/1/models/1/pipelines/1/runs/1/logs" ) logs = response.json() diff --git a/backend/tests/projects/toolmodels/pipelines/test_pipelines.py b/backend/tests/projects/toolmodels/pipelines/test_pipelines.py index b0a6d3ffe..456c25a69 100644 --- a/backend/tests/projects/toolmodels/pipelines/test_pipelines.py +++ b/backend/tests/projects/toolmodels/pipelines/test_pipelines.py @@ -12,11 +12,11 @@ from sqlalchemy import orm import capellacollab.projects.models as project_models -import capellacollab.projects.toolmodels.backups.crud as pipelines_crud -import capellacollab.projects.toolmodels.backups.models as pipelines_models import capellacollab.projects.toolmodels.models as toolmodels_models import capellacollab.projects.toolmodels.modelsources.git.models as git_models import capellacollab.projects.toolmodels.modelsources.t4c.models as models_t4c_models +import capellacollab.projects.toolmodels.pipelines.crud as pipelines_crud +import capellacollab.projects.toolmodels.pipelines.models as pipelines_models import capellacollab.sessions.operators import capellacollab.settings.modelsources.t4c.models as t4c_models import capellacollab.settings.modelsources.t4c.repositories.interface as t4c_repositories_interface @@ -63,7 +63,7 @@ def test_get_all_pipelines_of_capellamodel( include_commit_history: bool, ): response = client.get( - f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/backups/pipelines" + f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/pipelines" ) assert response.status_code == 200 @@ -82,7 +82,7 @@ def test_create_pipeline_of_capellamodel_git_model_does_not_exist( client: testclient.TestClient, ): response = client.post( - f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/backups/pipelines", + f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/pipelines", json={ "git_model_id": 0, "t4c_model_id": t4c_model.id, @@ -111,7 +111,7 @@ def test_create_pipeline( include_commit_history: bool, ): response = client.post( - f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/backups/pipelines", + f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/pipelines", json={ "git_model_id": git_model.id, "t4c_model_id": t4c_model.id, @@ -155,7 +155,7 @@ def mock_add_user_to_repository( ) response = client.post( - f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/backups/pipelines", + f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/pipelines", json={ "git_model_id": git_model.id, "t4c_model_id": t4c_model.id, @@ -199,7 +199,7 @@ def mock_remove_user_from_repository( ) response = client.delete( - f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/backups/pipelines/{pipeline.id}", + f"/api/v1/projects/{project.slug}/models/{capella_model.slug}/pipelines/{pipeline.id}", ) assert response.status_code == 204 diff --git a/frontend/package-lock.json b/frontend/package-lock.json index dda7f4ae0..708d3ac5b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -22,6 +22,7 @@ "@panzoom/panzoom": "^4.5.1", "@types/semver": "^7.5.4", "buffer": "^6.0.3", + "cronstrue": "^2.32.0", "file-saver": "^2.0.5", "http-status-codes": "^2.3.0", "ngx-cookie": "^6.0.1", @@ -34,6 +35,7 @@ "semver": "^7.5.4", "slugify": "^1.6.6", "tslib": "^2.6.2", + "yaml": "^2.3.3", "zone.js": "~0.13.3" }, "devDependencies": { @@ -244,397 +246,6 @@ } } }, - "node_modules/@angular-devkit/build-angular/node_modules/@babel/core": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", - "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.9", - "@babel/helper-compilation-targets": "^7.22.9", - "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/android-arm": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.17.tgz", - "integrity": "sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/android-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.17.tgz", - "integrity": "sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/android-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.17.tgz", - "integrity": "sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/darwin-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz", - "integrity": "sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/darwin-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.17.tgz", - "integrity": "sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.17.tgz", - "integrity": "sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/freebsd-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.17.tgz", - "integrity": "sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-arm": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.17.tgz", - "integrity": "sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.17.tgz", - "integrity": "sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-ia32": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.17.tgz", - "integrity": "sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-loong64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.17.tgz", - "integrity": "sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-mips64el": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.17.tgz", - "integrity": "sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-ppc64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.17.tgz", - "integrity": "sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-riscv64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.17.tgz", - "integrity": "sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-s390x": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.17.tgz", - "integrity": "sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.17.tgz", - "integrity": "sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/netbsd-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.17.tgz", - "integrity": "sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/openbsd-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.17.tgz", - "integrity": "sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/sunos-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.17.tgz", - "integrity": "sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/win32-arm64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.17.tgz", - "integrity": "sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/win32-ia32": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.17.tgz", - "integrity": "sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/win32-x64": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.17.tgz", - "integrity": "sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@angular-devkit/build-angular/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -693,44 +304,6 @@ "postcss": "^8.1.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/esbuild": { - "version": "0.18.17", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.17.tgz", - "integrity": "sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.17", - "@esbuild/android-arm64": "0.18.17", - "@esbuild/android-x64": "0.18.17", - "@esbuild/darwin-arm64": "0.18.17", - "@esbuild/darwin-x64": "0.18.17", - "@esbuild/freebsd-arm64": "0.18.17", - "@esbuild/freebsd-x64": "0.18.17", - "@esbuild/linux-arm": "0.18.17", - "@esbuild/linux-arm64": "0.18.17", - "@esbuild/linux-ia32": "0.18.17", - "@esbuild/linux-loong64": "0.18.17", - "@esbuild/linux-mips64el": "0.18.17", - "@esbuild/linux-ppc64": "0.18.17", - "@esbuild/linux-riscv64": "0.18.17", - "@esbuild/linux-s390x": "0.18.17", - "@esbuild/linux-x64": "0.18.17", - "@esbuild/netbsd-x64": "0.18.17", - "@esbuild/openbsd-x64": "0.18.17", - "@esbuild/sunos-x64": "0.18.17", - "@esbuild/win32-arm64": "0.18.17", - "@esbuild/win32-ia32": "0.18.17", - "@esbuild/win32-x64": "0.18.17" - } - }, "node_modules/@angular-devkit/build-angular/node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -1118,6 +691,80 @@ "typescript": ">=4.9.3 <5.2" } }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@angular/core": { "version": "16.2.11", "resolved": "https://registry.npmjs.org/@angular/core/-/core-16.2.11.tgz", @@ -1289,34 +936,34 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", - "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", - "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", + "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.0", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0", - "convert-source-map": "^2.0.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.8", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", + "json5": "^2.2.2", "semver": "^6.3.1" }, "engines": { @@ -1327,41 +974,6 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core/node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -1399,12 +1011,12 @@ } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.10.tgz", - "integrity": "sha512-Av0qubwDQxC56DoUReVDeLfMEjYYSN1nZrTUrWkXd7hpU73ymRANkbuDm3yni9npkn+RXy9nNbEJZEzXr7xrfQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", "dev": true, "dependencies": { - "@babel/types": "^7.22.10" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -1436,15 +1048,15 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.10.tgz", - "integrity": "sha512-5IBb77txKYQPpOEdUdIhBx8VrZyDCQ+H82H0+5dX1TmuscP5vJKEE3cKurjtIw/vFwzbVH48VweE78kVDBrqjA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz", + "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", - "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.15", "@babel/helper-optimise-call-expression": "^7.22.5", "@babel/helper-replace-supers": "^7.22.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", @@ -1468,9 +1080,9 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz", - "integrity": "sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", @@ -1494,9 +1106,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz", - "integrity": "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz", + "integrity": "sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==", "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -1558,12 +1170,12 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz", - "integrity": "sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -1622,14 +1234,14 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz", - "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-wrap-function": "^7.22.9" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -1639,13 +1251,13 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz", - "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { @@ -1719,14 +1331,28 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.9.tgz", - "integrity": "sha512-sZ+QzfauuUEfxSEjKFmi3qDSHgLsTPK/pEpoD/qonZKOtTPTLbf59oabPQ4rKekt9lFcj/hTZaOhWwFYrgjk+Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", "dev": true, "dependencies": { "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function/node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -1787,9 +1413,9 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.22.5", - "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.22.5.tgz", - "integrity": "sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==", + "version": "7.22.15", + "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.22.15.tgz", + "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1802,14 +1428,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz", - "integrity": "sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz", + "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.22.5" + "@babel/plugin-transform-optional-chaining": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -1822,6 +1448,7 @@ "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==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", @@ -1852,6 +1479,7 @@ "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==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-unicode-property-regex instead.", "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", @@ -2115,14 +1743,14 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.10.tgz", - "integrity": "sha512-eueE8lvKVzq5wIObKK/7dvoeKJ+xc6TvRn6aysIjS6pSCeLy7S/eVi7pEQknZqyqvzaNKdDtem8nUNTBgDVR2g==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.2.tgz", + "integrity": "sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.9", + "@babel/helper-remap-async-to-generator": "^7.22.20", "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { @@ -2165,9 +1793,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz", - "integrity": "sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz", + "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -2196,12 +1824,12 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz", - "integrity": "sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz", + "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.11", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, @@ -2213,18 +1841,18 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz", - "integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", + "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", "@babel/helper-optimise-call-expression": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", "@babel/helper-split-export-declaration": "^7.22.6", "globals": "^11.1.0" }, @@ -2252,9 +1880,9 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz", - "integrity": "sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz", + "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -2298,9 +1926,9 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz", - "integrity": "sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz", + "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2330,9 +1958,9 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz", - "integrity": "sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz", + "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2346,9 +1974,9 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz", - "integrity": "sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", + "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -2378,9 +2006,9 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz", - "integrity": "sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz", + "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2409,9 +2037,9 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz", - "integrity": "sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz", + "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2440,12 +2068,12 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz", - "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz", + "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -2456,12 +2084,12 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz", - "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", + "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-simple-access": "^7.22.5" }, @@ -2473,15 +2101,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz", - "integrity": "sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz", + "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==", "dev": true, "dependencies": { "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.0", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5" + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -2538,9 +2166,9 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz", - "integrity": "sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz", + "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2554,9 +2182,9 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz", - "integrity": "sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz", + "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2570,16 +2198,16 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz", - "integrity": "sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz", + "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.5", + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.22.5" + "@babel/plugin-transform-parameters": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -2605,9 +2233,9 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz", - "integrity": "sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz", + "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2621,9 +2249,9 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.10.tgz", - "integrity": "sha512-MMkQqZAZ+MGj+jGTG3OTuhKeBpNcO+0oCEbrGNEaOmiEn+1MzRyQlYsruGiU8RTK3zV6XwrVJTmwiDOyYK6J9g==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz", + "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2638,9 +2266,9 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz", - "integrity": "sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", + "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -2669,13 +2297,13 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz", - "integrity": "sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz", + "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.11", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, @@ -3034,438 +2662,102 @@ "regenerator-runtime": "^0.13.11" }, "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "devOptional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], + "node_modules/@babel/template": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], + "node_modules/@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", "dev": true, - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "devOptional": true, "engines": { - "node": ">=12" + "node": ">=0.1.90" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true, - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=12" + "node": ">=10.0.0" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz", + "integrity": "sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==", "cpu": [ - "x64" + "arm64" ], "dev": true, "optional": true, "os": [ - "win32" + "darwin" ], "engines": { "node": ">=12" @@ -3487,9 +2779,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.1.tgz", - "integrity": "sha512-O7x6dMstWLn2ktjcoiNLDkAGG2EjveHL+Vvc+n0fXumkJYAcSqcVYKtwDU+hDZ0uDUsnUagSYaZrOLAYE8un1A==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -3541,9 +2833,9 @@ "dev": true }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -3594,6 +2886,11 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", @@ -3756,9 +3053,9 @@ } }, "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==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true, "engines": { "node": ">=6.0.0" @@ -3790,21 +3087,15 @@ "dev": 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==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@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==", - "dev": true - }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", @@ -4689,6 +3980,30 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@npmcli/node-gyp": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", @@ -4767,216 +4082,72 @@ "dev": true, "dependencies": { "nx": "16.5.1" - }, - "bin": { - "tao": "index.js" - } - }, - "node_modules/@nx/devkit": { - "version": "16.5.1", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-16.5.1.tgz", - "integrity": "sha512-T1acZrVVmJw/sJ4PIGidCBYBiBqlg/jT9e8nIGXLSDS20xcLvfo4zBQf8UZLrmHglnwwpDpOWuVJCp2rYA5aDg==", - "dev": true, - "dependencies": { - "@nrwl/devkit": "16.5.1", - "ejs": "^3.1.7", - "ignore": "^5.0.4", - "semver": "7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "nx": ">= 15 <= 17" - } - }, - "node_modules/@nx/devkit/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/devkit/node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/devkit/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@nx/nx-darwin-arm64": { - "version": "16.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-16.5.1.tgz", - "integrity": "sha512-q98TFI4B/9N9PmKUr1jcbtD4yAFs1HfYd9jUXXTQOlfO9SbDjnrYJgZ4Fp9rMNfrBhgIQ4x1qx0AukZccKmH9Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-darwin-x64": { - "version": "16.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-16.5.1.tgz", - "integrity": "sha512-j9HmL1l8k7EVJ3eOM5y8COF93gqrydpxCDoz23ZEtsY+JHY77VAiRQsmqBgEx9GGA2dXi9VEdS67B0+1vKariw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-freebsd-x64": { - "version": "16.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-16.5.1.tgz", - "integrity": "sha512-CXSPT01aVS869tvCCF2tZ7LnCa8l41wJ3mTVtWBkjmRde68E5Up093hklRMyXb3kfiDYlfIKWGwrV4r0eH6x1A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "16.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-16.5.1.tgz", - "integrity": "sha512-BhrumqJSZCWFfLFUKl4CAUwR0Y0G2H5EfFVGKivVecEQbb+INAek1aa6c89evg2/OvetQYsJ+51QknskwqvLsA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "16.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-16.5.1.tgz", - "integrity": "sha512-x7MsSG0W+X43WVv7JhiSq2eKvH2suNKdlUHEG09Yt0vm3z0bhtym1UCMUg3IUAK7jy9hhLeDaFVFkC6zo+H/XQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/nx-linux-arm64-musl": { - "version": "16.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-16.5.1.tgz", - "integrity": "sha512-J+/v/mFjOm74I0PNtH5Ka+fDd+/dWbKhpcZ2R1/6b9agzZk+Ff/SrwJcSYFXXWKbPX+uQ4RcJoytT06Zs3s0ow==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + }, + "bin": { + "tao": "index.js" } }, - "node_modules/@nx/nx-linux-x64-gnu": { + "node_modules/@nx/devkit": { "version": "16.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-16.5.1.tgz", - "integrity": "sha512-igooWJ5YxQ94Zft7IqgL+Lw0qHaY15Btw4gfK756g/YTYLZEt4tTvR1y6RnK/wdpE3sa68bFTLVBNCGTyiTiDQ==", - "cpu": [ - "x64" - ], + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-16.5.1.tgz", + "integrity": "sha512-T1acZrVVmJw/sJ4PIGidCBYBiBqlg/jT9e8nIGXLSDS20xcLvfo4zBQf8UZLrmHglnwwpDpOWuVJCp2rYA5aDg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@nrwl/devkit": "16.5.1", + "ejs": "^3.1.7", + "ignore": "^5.0.4", + "semver": "7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "nx": ">= 15 <= 17" } }, - "node_modules/@nx/nx-linux-x64-musl": { - "version": "16.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-16.5.1.tgz", - "integrity": "sha512-zF/exnPqFYbrLAduGhTmZ7zNEyADid2bzNQiIjJkh8Y6NpDwrQIwVIyvIxqynsjMrIs51kBH+8TUjKjj2Jgf5A==", - "cpu": [ - "x64" - ], + "node_modules/@nx/devkit/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "16.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-16.5.1.tgz", - "integrity": "sha512-qtqiLS9Y9TYyAbbpq58kRoOroko4ZXg5oWVqIWFHoxc5bGPweQSJCROEqd1AOl2ZDC6BxfuVHfhDDop1kK05WA==", - "cpu": [ - "arm64" - ], + "node_modules/@nx/devkit/node_modules/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/@nx/nx-win32-x64-msvc": { + "node_modules/@nx/devkit/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@nx/nx-darwin-arm64": { "version": "16.5.1", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-16.5.1.tgz", - "integrity": "sha512-kUJBLakK7iyA9WfsGGQBVennA4jwf5XIgm0lu35oMOphtZIluvzItMt0EYBmylEROpmpEIhHq0P6J9FA+WH0Rg==", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-16.5.1.tgz", + "integrity": "sha512-q98TFI4B/9N9PmKUr1jcbtD4yAFs1HfYd9jUXXTQOlfO9SbDjnrYJgZ4Fp9rMNfrBhgIQ4x1qx0AukZccKmH9Q==", "cpu": [ - "x64" + "arm64" ], "dev": true, "optional": true, "os": [ - "win32" + "darwin" ], "engines": { "node": ">= 10" @@ -5083,9 +4254,9 @@ } }, "node_modules/@sigstore/bundle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.0.0.tgz", - "integrity": "sha512-yLvrWDOh6uMOUlFCTJIZEnwOT9Xte7NPXUqVexEKGSF5XtBAuSg5du0kn3dRR0p47a4ah10Y0mNt8+uyeQXrBQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", + "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==", "dependencies": { "@sigstore/protobuf-specs": "^0.2.0" }, @@ -5094,9 +4265,22 @@ } }, "node_modules/@sigstore/protobuf-specs": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.0.tgz", - "integrity": "sha512-8ZhZKAVfXjIspDWwm3D3Kvj0ddbJ0HqDZ/pOs5cx88HpT8mVsotFrg7H1UMnXOuDHz6Zykwxn4mxG3QLuN+RUg==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", + "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz", + "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==", + "dependencies": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "make-fetch-happen": "^11.0.1" + }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -5142,11 +4326,12 @@ } }, "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, "engines": { - "node": ">= 10" + "node": ">= 6" } }, "node_modules/@tufjs/canonical-json": { @@ -5236,18 +4421,18 @@ "dev": true }, "node_modules/@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "version": "2.8.15", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.15.tgz", + "integrity": "sha512-n91JxbNLD8eQIuXDIChAN1tCKNWCEgpceU9b7ZMbFA+P+Q4yIeh80jizFLEvolRPc1ES0VdwFlGv+kJTSirogw==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/eslint": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.1.tgz", - "integrity": "sha512-XpNDc4Z5Tb4x+SW1MriMVeIsMoONHCkWFMkR/aPJbzEsxqHy+4Glu/BqTdPrApfDeMaXbtNh6bseNgl5KaWrSg==", + "version": "8.44.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", + "integrity": "sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==", "dev": true, "dependencies": { "@types/estree": "*", @@ -5255,9 +4440,9 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.6.tgz", + "integrity": "sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==", "dev": true, "dependencies": { "@types/eslint": "*", @@ -5265,9 +4450,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.4.tgz", + "integrity": "sha512-2JwWnHK9H+wUZNorf2Zr6ves96WHoWDJIftkcxPKsS7Djta6Zu519LarhRNljPXkpsZR2ZMwNCPeW7omW07BJw==", "dev": true }, "node_modules/@types/express": { @@ -5301,9 +4486,9 @@ "dev": true }, "node_modules/@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", + "integrity": "sha512-V46MYLFp08Wf2mmaBhvgjStM3tPa+2GAdy/iqoX+noX1//zje2x4XmrIU0cAwyClATsTmahbtoQ2EwP7I5WSiA==" }, "node_modules/@types/http-errors": { "version": "2.0.3", @@ -5327,9 +4512,9 @@ "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", "dev": true }, "node_modules/@types/json5": { @@ -5345,9 +4530,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", - "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", + "version": "20.8.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", + "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -5434,16 +4619,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.0.tgz", - "integrity": "sha512-lgX7F0azQwRPB7t7WAyeHWVfW1YJ9NIgd9mvGhfQpRY56X6AVf8mwM8Wol+0z4liE7XX3QOt8MN1rUKCfSjRIA==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.1.tgz", + "integrity": "sha512-w0tiiRc9I4S5XSXXrMHOWgHgxbrBn1Ro+PmiYhSg2ZVdxrAJtQgzU5o2m1BfP6UOn7Vxcc6152vFjQfmZR4xEg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/type-utils": "6.9.0", - "@typescript-eslint/utils": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/type-utils": "6.9.1", + "@typescript-eslint/utils": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -5468,31 +4653,14 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz", - "integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.0.tgz", - "integrity": "sha512-XXeahmfbpuhVbhSOROIzJ+b13krFmgtc4GlEuu1WBT+RpyGPIA4Y/eGnXzjbDj5gZLzpAXO/sj+IF/x2GtTMjQ==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.1.tgz", + "integrity": "sha512-eh2oHaUKCK58qIeYp19F5V5TbpM52680sB4zNSz29VBQPTWIlE/hCj5P5B1AChxECe/fmZlspAWFuRniep1Skg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.9.0", - "@typescript-eslint/utils": "6.9.0", + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/utils": "6.9.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -5512,58 +4680,18 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", - "integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz", - "integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.0.tgz", - "integrity": "sha512-5Wf+Jsqya7WcCO8me504FBigeQKVLAMPmUzYgDbWchINNh1KJbxCgVya3EQ2MjvJMVeXl3pofRmprqX6mfQkjQ==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", + "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/typescript-estree": "6.9.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", "semver": "^7.5.4" }, "engines": { @@ -5577,33 +4705,16 @@ "eslint": "^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", - "integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.9.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/parser": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.0.tgz", - "integrity": "sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.1.tgz", + "integrity": "sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/typescript-estree": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", "debug": "^4.3.4" }, "engines": { @@ -5622,88 +4733,14 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz", - "integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", - "integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz", - "integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", - "integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.9.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.0.tgz", - "integrity": "sha512-lAT1Uau20lQyjoLUQ5FUMSX/dS07qux9rYd5FGzKz/Kf8W8ccuvMyldb8hadHdK/qOI7aikvQWqulnEq2nCEYA==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.1.tgz", + "integrity": "sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.0", - "@typescript-eslint/visitor-keys": "6.7.0" + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -5798,9 +4835,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.0.tgz", - "integrity": "sha512-ihPfvOp7pOcN/ysoj0RpBPOx3HQTJTrIN8UZK+WFd3/iDeFHHqeyYxa4hQk4rMhsz9H9mXpR61IzwlBVGXtl9Q==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.1.tgz", + "integrity": "sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -5811,13 +4848,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.0.tgz", - "integrity": "sha512-dPvkXj3n6e9yd/0LfojNU8VMUGHWiLuBZvbM6V6QYD+2qxqInE7J+J/ieY2iGwR9ivf/R/haWGkIj04WVUeiSQ==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.1.tgz", + "integrity": "sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.0", - "@typescript-eslint/visitor-keys": "6.7.0", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/visitor-keys": "6.9.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -5960,12 +4997,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.0.tgz", - "integrity": "sha512-/C1RVgKFDmGMcVGeD8HjKv2bd72oI1KxQDeY8uc66gw9R0OK0eMq48cA+jv9/2Ag6cdrsUGySm1yzYmfz0hxwQ==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.1.tgz", + "integrity": "sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.0", + "@typescript-eslint/types": "6.9.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -6307,9 +5344,9 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -6406,12 +5443,10 @@ } }, "node_modules/agentkeepalive": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", - "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", "dependencies": { - "debug": "^4.1.0", - "depd": "^2.0.0", "humanize-ms": "^1.2.1" }, "engines": { @@ -6531,7 +5566,6 @@ "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" }, @@ -6783,9 +5817,9 @@ } }, "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", "dev": true, "dependencies": { "follow-redirects": "^1.15.0", @@ -6793,6 +5827,20 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/axobject-query": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", @@ -6836,13 +5884,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz", - "integrity": "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz", + "integrity": "sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==", "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.4.2", + "@babel/helper-define-polyfill-provider": "^0.4.3", "semver": "^6.3.1" }, "peerDependencies": { @@ -6859,25 +5907,25 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz", - "integrity": "sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==", + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.6.tgz", + "integrity": "sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.2", - "core-js-compat": "^3.31.0" + "@babel/helper-define-polyfill-provider": "^0.4.3", + "core-js-compat": "^3.33.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz", - "integrity": "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz", + "integrity": "sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.2" + "@babel/helper-define-polyfill-provider": "^0.4.3" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -7186,9 +6234,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.21.10", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", - "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "dev": true, "funding": [ { @@ -7205,10 +6253,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001517", - "electron-to-chromium": "^1.4.477", + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.11" + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -7263,15 +6311,15 @@ } }, "node_modules/cacache": { - "version": "17.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.3.tgz", - "integrity": "sha512-jAdjGxmPxZh0IipMdR7fK/4sDSrHMLUV0+GvVUsjwyGNKHsh79kW/otg+GkbXwl6Uzvy9wsvHOX4nUoWldeZMg==", + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", "dependencies": { "@npmcli/fs": "^3.1.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^7.7.1", - "minipass": "^5.0.0", + "minipass": "^7.0.3", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", @@ -7284,6 +6332,35 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/cacache/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==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/cacache/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -7292,6 +6369,28 @@ "node": ">=12" } }, + "node_modules/cacache/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/cacheable-lookup": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", @@ -7301,14 +6400,14 @@ } }, "node_modules/cacheable-request": { - "version": "10.2.12", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.12.tgz", - "integrity": "sha512-qtWGB5kn2OLjx47pYUkWicyOpK1vy9XZhq8yRTXOy+KAmjjESSRLx6SiExnnaGGUP1NM6/vmygMu0fGylNh9tw==", + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", "dependencies": { - "@types/http-cache-semantics": "^4.0.1", + "@types/http-cache-semantics": "^4.0.2", "get-stream": "^6.0.1", "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.2", + "keyv": "^4.5.3", "mimic-response": "^4.0.0", "normalize-url": "^8.0.0", "responselike": "^3.0.0" @@ -7359,9 +6458,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001539", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001539.tgz", - "integrity": "sha512-hfS5tE8bnNiNvEOEkm8HElUHroYwlqMMENEzELymy77+tJ6m+gA2krtHl5hxJaj71OlpC2cHZbdSMX1/YEqEkA==", + "version": "1.0.30001559", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001559.tgz", + "integrity": "sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA==", "dev": true, "funding": [ { @@ -7382,7 +6481,6 @@ "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", @@ -7443,9 +6541,9 @@ } }, "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "funding": [ { "type": "github", @@ -7560,7 +6658,6 @@ "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" } @@ -7568,8 +6665,7 @@ "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 + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/color-support": { "version": "1.1.3", @@ -7874,12 +6970,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.0.tgz", - "integrity": "sha512-7a9a3D1k4UCVKnLhrgALyFcP7YCsLOQIxPd0dKjf/6GuPcgyiGP70ewWdCGrSK7evyhymi0qO4EqCmSJofDeYw==", + "version": "3.33.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.2.tgz", + "integrity": "sha512-axfo+wxFVxnqf8RvxTzoAlzW4gRoacrHeoFlc9n0x50+7BEyZL/Rt3hicaED1/CEd7I6tPCPVUYcJwCMO5XUYw==", "dev": true, "dependencies": { - "browserslist": "^4.21.9" + "browserslist": "^4.22.1" }, "funding": { "type": "opencollective", @@ -7906,14 +7002,14 @@ } }, "node_modules/cosmiconfig": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", - "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, "dependencies": { - "import-fresh": "^3.2.1", + "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", + "parse-json": "^5.2.0", "path-type": "^4.0.0" }, "engines": { @@ -7921,6 +7017,14 @@ }, "funding": { "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/cosmiconfig/node_modules/argparse": { @@ -8026,6 +7130,14 @@ "node": ">=8" } }, + "node_modules/cronstrue": { + "version": "2.41.0", + "resolved": "https://registry.npmjs.org/cronstrue/-/cronstrue-2.41.0.tgz", + "integrity": "sha512-3ZS3eMJaxMRBGmDauKCKbyIRgVcph6uSpkhSbbZvvJWkelHiSTzGJbBqmu8io7Hspd2F45bQKnC1kzoNvtku2g==", + "bin": { + "cronstrue": "bin/cli.js" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -8334,6 +7446,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -8566,9 +7679,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.503", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.503.tgz", - "integrity": "sha512-LF2IQit4B0VrUHFeQkWhZm97KuJSGF2WJqq1InpY+ECpFRkXd8yTIaTtJxsO0OKDmiBYwWqcrNaXOurn2T2wiA==", + "version": "1.4.571", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.571.tgz", + "integrity": "sha512-Sc+VtKwKCDj3f/kLBjdyjMpNzoZsU6WuL/wFb6EH8USmHEcebxRXcRrVpOpayxd52tuey4RUDpUsw5OS5LhJqg==", "dev": true }, "node_modules/emoji-regex": { @@ -8625,9 +7738,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.1.tgz", - "integrity": "sha512-mGqhI+D7YxS9KJMppR6Iuo37Ed3abhU8NdfgSvJSDUafQutrN+sPTncJYTyM9+tkhSmWodKtVYGPPHyXJEwEQA==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.3.tgz", + "integrity": "sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==", "dev": true, "dependencies": { "@types/cookie": "^0.4.1", @@ -8638,20 +7751,41 @@ "cookie": "~0.4.1", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~5.1.0", + "engine.io-parser": "~5.2.1", "ws": "~8.11.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/engine.io-parser": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.1.0.tgz", - "integrity": "sha512-enySgNiK5tyZFynt3z7iqBR+Bto9EVVVvDFuTT0ioHCGbzirZVGDGiQjZzEp8hWl6hd5FSVytJGuScX1C1C35w==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "dev": true, "engines": { "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/enhanced-resolve": { @@ -8786,9 +7920,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", - "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", + "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", "dev": true }, "node_modules/es-set-tostringtag": { @@ -8832,9 +7966,9 @@ } }, "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.17.tgz", + "integrity": "sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==", "dev": true, "hasInstallScript": true, "bin": { @@ -8844,28 +7978,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" + "@esbuild/android-arm": "0.18.17", + "@esbuild/android-arm64": "0.18.17", + "@esbuild/android-x64": "0.18.17", + "@esbuild/darwin-arm64": "0.18.17", + "@esbuild/darwin-x64": "0.18.17", + "@esbuild/freebsd-arm64": "0.18.17", + "@esbuild/freebsd-x64": "0.18.17", + "@esbuild/linux-arm": "0.18.17", + "@esbuild/linux-arm64": "0.18.17", + "@esbuild/linux-ia32": "0.18.17", + "@esbuild/linux-loong64": "0.18.17", + "@esbuild/linux-mips64el": "0.18.17", + "@esbuild/linux-ppc64": "0.18.17", + "@esbuild/linux-riscv64": "0.18.17", + "@esbuild/linux-s390x": "0.18.17", + "@esbuild/linux-x64": "0.18.17", + "@esbuild/netbsd-x64": "0.18.17", + "@esbuild/openbsd-x64": "0.18.17", + "@esbuild/sunos-x64": "0.18.17", + "@esbuild/win32-arm64": "0.18.17", + "@esbuild/win32-ia32": "0.18.17", + "@esbuild/win32-x64": "0.18.17" } }, "node_modules/esbuild-wasm": { @@ -8910,7 +8044,6 @@ "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" } @@ -9092,17 +8225,17 @@ } }, "node_modules/eslint-plugin-deprecation/node_modules/@typescript-eslint/utils": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.0.tgz", - "integrity": "sha512-MfCq3cM0vh2slSikQYqK2Gq52gvOhe57vD2RM3V4gQRZYX4rDPnKLu5p6cm89+LJiGlwEXU8hkYxhqqEC/V3qA==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.1.tgz", + "integrity": "sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.0", - "@typescript-eslint/types": "6.7.0", - "@typescript-eslint/typescript-estree": "6.7.0", + "@typescript-eslint/scope-manager": "6.9.1", + "@typescript-eslint/types": "6.9.1", + "@typescript-eslint/typescript-estree": "6.9.1", "semver": "^7.5.4" }, "engines": { @@ -9363,9 +8496,9 @@ } }, "node_modules/eslint/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -9598,12 +8731,6 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/execa/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, "node_modules/exponential-backoff": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", @@ -9994,28 +9121,29 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=12.0.0" } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", "dev": true, "funding": [ { @@ -10056,10 +9184,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", "dev": true, "dependencies": { "asynckit": "^0.4.0", @@ -10096,9 +9235,9 @@ } }, "node_modules/fraction.js": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.6.tgz", - "integrity": "sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "dev": true, "engines": { "node": "*" @@ -10138,20 +9277,28 @@ } }, "node_modules/fs-minipass": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.2.tgz", - "integrity": "sha512-2GAfyfoaCDRrM6jaOS3UsBts8yJ55VioXdWcOL7dK9zdAuKT71+WBA4ifnNYqVjYv+4SsPxjK0JT4yIIn4cA/g==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "dependencies": { - "minipass": "^5.0.0" + "minipass": "^7.0.3" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/fs-monkey": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", - "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", + "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", "dev": true }, "node_modules/fs.realpath": { @@ -10160,9 +9307,9 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -10226,11 +9373,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/gauge/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -10312,21 +9454,19 @@ } }, "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -10349,26 +9489,12 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, - "node_modules/glob/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==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "node_modules/glob/node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.10.0" } }, "node_modules/global-dirs": { @@ -10514,7 +9640,6 @@ "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" } @@ -10791,11 +9916,12 @@ } }, "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, "dependencies": { - "@tootallnate/once": "2", + "@tootallnate/once": "1", "agent-base": "6", "debug": "4" }, @@ -10971,9 +10097,9 @@ } }, "node_modules/immutable": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.1.tgz", - "integrity": "sha512-lj9cnmB/kVS0QHsJnYKD1uo3o39nrbKxszjnqS9Fr6NB7bZzW45U6WSGBPKXDL/CvDKqDNPA4r3DoDQ8GTxo2A==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", + "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", "dev": true }, "node_modules/import-fresh": { @@ -11025,6 +10151,11 @@ "node": ">=8" } }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -11650,17 +10781,17 @@ } }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-lib-report/node_modules/has-flag": { @@ -11708,9 +10839,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -11870,9 +11001,9 @@ } }, "node_modules/jiti": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", - "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", "dev": true, "bin": { "jiti": "bin/jiti.js" @@ -11925,93 +11056,35 @@ "nwsapi": "^2.2.0", "parse5": "6.0.1", "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom/node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jsdom/node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jsdom/node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jsdom/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/jsdom/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "dev": true, + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, "engines": { - "node": ">=8.3.0" + "node": ">=10" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "canvas": "^2.5.0" }, "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { + "canvas": { "optional": true } } }, + "node_modules/jsdom/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -12032,8 +11105,7 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-parse-helpfulerror": { "version": "1.0.3", @@ -12189,26 +11261,6 @@ "url": "https://github.com/sponsors/mattlewis92" } }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/karma-coverage-istanbul-reporter/node_modules/istanbul-lib-source-maps": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", @@ -12247,15 +11299,6 @@ "node": ">=6" } }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/karma-coverage-istanbul-reporter/node_modules/pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -12336,35 +11379,6 @@ "source-map-support": "^0.5.5" } }, - "node_modules/karma/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/karma/node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/karma/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -12402,9 +11416,9 @@ } }, "node_modules/keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dependencies": { "json-buffer": "3.0.1" } @@ -12792,29 +11806,20 @@ } }, "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "dependencies": { - "semver": "^6.0.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/make-fetch-happen": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", @@ -12840,6 +11845,27 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/make-fetch-happen/node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/make-fetch-happen/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -13043,11 +12069,11 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/minipass-fetch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.3.tgz", - "integrity": "sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", "dependencies": { - "minipass": "^5.0.0", + "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, @@ -13058,6 +12084,14 @@ "encoding": "^0.1.13" } }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", @@ -13395,15 +12429,15 @@ } }, "node_modules/node-gyp": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", - "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", + "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "glob": "^7.1.4", "graceful-fs": "^4.2.6", - "make-fetch-happen": "^11.0.3", + "make-fetch-happen": "^10.0.3", "nopt": "^6.0.0", "npmlog": "^6.0.0", "rimraf": "^3.0.2", @@ -13415,47 +12449,239 @@ "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": "^12.13 || ^14.13 || >=16" + "node": "^12.13 || ^14.13 || >=16" + } + }, + "node_modules/node-gyp-build": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", + "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp/node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/node-gyp/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/node-gyp/node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/node-gyp/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/node-gyp/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/node-gyp/node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-gyp/node_modules/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" } }, - "node_modules/node-gyp-build": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", - "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", - "dev": true, + "node_modules/node-gyp/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/node-gyp/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/node-gyp/node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "minipass": "^3.1.1" }, "engines": { - "node": "*" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dependencies": { + "unique-slug": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/node-gyp/node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/node-gyp/node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dependencies": { + "imurmurhash": "^0.1.4" + }, "engines": { - "node": ">=0.10.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/node-gyp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/node-releases": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", @@ -13803,6 +13029,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/npm-check-updates/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/npm-check-updates/node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -13913,9 +13160,9 @@ } }, "node_modules/npm-install-checks": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.1.1.tgz", - "integrity": "sha512-dH3GmQL4vsPtld59cOn8uY0iOqRmqKvV+DLGwNXV/Q7MDgD2QfOADWd/mFXcIE5LVhYYGjA3baz6W9JneqnuCw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", + "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", "dependencies": { "semver": "^7.1.1" }, @@ -17797,9 +17044,9 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", - "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", "engines": { "node": "14 || >=16.14" } @@ -17994,6 +17241,20 @@ "node": ">=16" } }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -18412,9 +17673,9 @@ "dev": true }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -18624,6 +17885,35 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/read-package-json/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==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/read-package-json/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/read-package-json/node_modules/json-parse-even-better-errors": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", @@ -18632,6 +17922,20 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/read-package-json/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -18670,9 +17974,9 @@ "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==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", "dev": true, "dependencies": { "regenerate": "^1.4.2" @@ -18910,12 +18214,6 @@ "node": ">=8" } }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -18953,37 +18251,10 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/rollup": { - "version": "3.26.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.3.tgz", - "integrity": "sha512-7Tin0C8l86TkpcMtXvQu6saWH93nhG3dGQ1/+l5V2TDMceTxO7kDiK6GzbfLWNNxqJXm591PcEZUozZm51ogwQ==", + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -19152,9 +18423,9 @@ } }, "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", "dev": true, "optional": true }, @@ -19511,23 +18782,18 @@ } }, "node_modules/signal-exit": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", - "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/sigstore": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.8.0.tgz", - "integrity": "sha512-ogU8qtQ3VFBawRJ8wjsBEX/vIFeHuGs1fm4jZtjWQwjo8pfAt7T/rh+udlAN4+QUe0IzA8qRSc/YZ7dHP6kh+w==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz", + "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==", "dependencies": { - "@sigstore/bundle": "^1.0.0", + "@sigstore/bundle": "^1.1.0", "@sigstore/protobuf-specs": "^0.2.0", + "@sigstore/sign": "^1.0.0", "@sigstore/tuf": "^1.0.3", "make-fetch-happen": "^11.0.1" }, @@ -19569,21 +18835,21 @@ } }, "node_modules/socket.io": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.1.tgz", - "integrity": "sha512-W+utHys2w//dhFjy7iQQu9sGd3eokCjGbl2r59tyLqNiJJBdIebn3GAKEXBr3osqHTObJi2die/25bCx2zsaaw==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", + "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", "dev": true, "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.0", + "engine.io": "~6.5.2", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" }, "engines": { - "node": ">=10.0.0" + "node": ">=10.2.0" } }, "node_modules/socket.io-adapter": { @@ -19595,6 +18861,27 @@ "ws": "~8.11.0" } }, + "node_modules/socket.io-adapter/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", @@ -19748,9 +19035,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==" + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==" }, "node_modules/spdy": { "version": "4.0.2", @@ -19789,16 +19076,24 @@ "dev": true }, "node_modules/ssri": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.4.tgz", - "integrity": "sha512-12+IR2CB2C28MMAw0Ncqwj5QbTcs0nGIhgJzYWzDkb21vWmfNI83KS4f3Ci6GI98WreIfG7o9UXp3C0qbpA8nQ==", + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", "dependencies": { - "minipass": "^5.0.0" + "minipass": "^7.0.3" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/ssri/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -20074,7 +19369,6 @@ "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" }, @@ -20168,9 +19462,9 @@ } }, "node_modules/tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -20358,40 +19652,10 @@ "node": ">=8" } }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/test-exclude/node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "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 + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, "node_modules/thenify": { "version": "3.3.1", @@ -20513,9 +19777,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", - "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", "dev": true, "engines": { "node": ">=16.13.0" @@ -20723,9 +19987,9 @@ } }, "node_modules/ua-parser-js": { - "version": "0.7.35", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.35.tgz", - "integrity": "sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g==", + "version": "0.7.37", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.37.tgz", + "integrity": "sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==", "dev": true, "funding": [ { @@ -20735,6 +19999,10 @@ { "type": "paypal", "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" } ], "engines": { @@ -20865,9 +20133,9 @@ } }, "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==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "funding": [ { @@ -21715,18 +20983,13 @@ "typedarray-to-buffer": "^3.1.5" } }, - "node_modules/write-file-atomic/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", "dev": true, "engines": { - "node": ">=10.0.0" + "node": ">=8.3.0" }, "peerDependencies": { "bufferutil": "^4.0.1", @@ -21780,10 +21043,9 @@ "dev": true }, "node_modules/yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", - "dev": true, + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", + "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", "engines": { "node": ">= 14" } diff --git a/frontend/package.json b/frontend/package.json index 8aca4308d..ef030aada 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,6 +27,7 @@ "@panzoom/panzoom": "^4.5.1", "@types/semver": "^7.5.4", "buffer": "^6.0.3", + "cronstrue": "^2.32.0", "file-saver": "^2.0.5", "http-status-codes": "^2.3.0", "ngx-cookie": "^6.0.1", @@ -39,6 +40,7 @@ "semver": "^7.5.4", "slugify": "^1.6.6", "tslib": "^2.6.2", + "yaml": "^2.3.3", "zone.js": "~0.13.3" }, "devDependencies": { diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index 5dc705859..110860dd2 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -5,8 +5,12 @@ import { NgModule } from '@angular/core'; import { Data, RouterModule, Routes } from '@angular/router'; +import { CreatePluginComponent } from 'src/app/plugins/store/create-plugin/create-plugin.component'; +import { PluginStoreOverviewComponent } from 'src/app/plugins/store/plugin-store-overview/plugin-store-overview.component'; +import { CreatePipelineComponent } from 'src/app/projects/models/backup-settings/create-pipeline/create-pipeline.component'; import { JobRunOverviewComponent } from 'src/app/projects/models/backup-settings/job-run-overview/job-run-overview.component'; import { PipelineRunWrapperComponent } from 'src/app/projects/models/backup-settings/pipeline-runs/wrapper/pipeline-run-wrapper/pipeline-run-wrapper.component'; +import { TriggerPipelineComponent } from 'src/app/projects/models/backup-settings/trigger-pipeline/trigger-pipeline.component'; import { ViewLogsDialogComponent } from 'src/app/projects/models/backup-settings/view-logs-dialog/view-logs-dialog.component'; import { PipelineWrapperComponent } from 'src/app/projects/models/backup-settings/wrapper/pipeline-wrapper/pipeline-wrapper.component'; import { ModelRestrictionsComponent } from 'src/app/projects/models/model-restrictions/model-restrictions.component'; @@ -20,6 +24,8 @@ import { AuthGuardService } from './general/auth/auth-guard/auth-guard.service'; import { AuthRedirectComponent } from './general/auth/auth-redirect/auth-redirect.component'; import { LogoutComponent } from './general/auth/logout/logout/logout.component'; import { LogoutRedirectComponent } from './general/auth/logout/logout-redirect/logout-redirect.component'; +import { PluginDetailsComponent } from './plugins/store/plugin-detail/plugin-details.component'; +import { PluginWrapperComponent } from './plugins/store/plugin-wrapper/plugin-wrapper.component'; import { CreateProjectComponent } from './projects/create-project/create-project.component'; import { CreateModelComponent } from './projects/models/create-model/create-model.component'; import { ModelDescriptionComponent } from './projects/models/model-description/model-description.component'; @@ -76,6 +82,48 @@ const routes: Routes = [ }, ], }, + { + path: 'plugins', + data: { breadcrumb: 'Plugins', redirect: '/plugins' }, + children: [ + { + path: '', + data: { breadcrumb: 'overview' }, + component: PluginStoreOverviewComponent, + }, + { + path: 'create', + data: { breadcrumb: 'create' }, + component: CreatePluginComponent, + }, + ], + }, + { + path: 'plugin', + data: { breadcrumb: 'Plugins', redirect: '/plugins' }, + children: [ + { + path: ':plugin', + data: { + breadcrumb: (data: Data) => + data.plugin?.content.metadata.displayName || + data.plugin?.content.metadata.id, + redirect: (data: Data) => `/plugin/${data.plugin?.id}`, + }, + component: PluginWrapperComponent, + children: [ + { + path: '', + data: { + breadcrumb: 'details', + redirect: (data: Data) => `/plugin/${data.plugin?.id}`, + }, + component: PluginDetailsComponent, + }, + ], + }, + ], + }, { path: 'project', data: { breadcrumb: 'Projects', redirect: '/projects' }, @@ -118,7 +166,7 @@ const routes: Routes = [ { path: ':model', data: { - breadcrumb: (data: Data) => data.model?.slug, + breadcrumb: (data: Data) => data.model?.name, redirect: (data: Data) => `/project/${data.project?.slug}`, }, @@ -160,6 +208,35 @@ const routes: Routes = [ }, component: ModelRestrictionsComponent, }, + { + path: 'pipelines', + data: { + breadcrumb: 'Pipelines', + redirect: (data: Data) => + `/project/${data.project?.slug}/models/${data.model?.slug}/pipelines`, + }, + children: [ + { + path: '', + data: { + breadcrumb: 'Overview', + redirect: (data: Data) => + `/project/${data.project?.slug}/models/${data.model?.slug}/pipelines`, + }, + component: TriggerPipelineComponent, + }, + { + path: 'create', + data: { + breadcrumb: 'Create', + redirect: (data: Data) => + `/project/${data.project?.slug}/models/${data.model?.slug}/pipelines/create`, + }, + component: CreatePipelineComponent, + }, + ], + }, + { path: 'pipeline', data: { @@ -180,14 +257,14 @@ const routes: Routes = [ { path: 'runs', data: { - breadcrumb: () => 'runs', + breadcrumb: 'Runs', }, component: JobRunOverviewComponent, }, { path: 'run', data: { - breadcrumb: 'runs', + breadcrumb: 'Runs', redirect: (data: Data) => `/project/${data.project?.slug}/model/${data.model?.slug}/pipeline/${data.pipeline?.id}/runs`, }, @@ -204,7 +281,7 @@ const routes: Routes = [ children: [ { path: 'logs', - data: { breadcrumb: 'logs' }, + data: { breadcrumb: 'Logs' }, component: ViewLogsDialogComponent, }, ], diff --git a/frontend/src/app/app.component.css b/frontend/src/app/app.component.css index 825d20d69..139358d77 100644 --- a/frontend/src/app/app.component.css +++ b/frontend/src/app/app.component.css @@ -38,3 +38,7 @@ .navBar { min-height: 65px; } + +.mat-drawer-container { + background-color: white; +} diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index f01be1e91..40834bcaa 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -72,8 +72,17 @@ import { MatCardOverviewSkeletonLoaderComponent } from './helpers/skeleton-loade import { MatCheckboxLoaderComponent } from './helpers/skeleton-loaders/mat-checkbox-loader/mat-checkbox-loader.component'; import { MatListSkeletonLoaderComponent } from './helpers/skeleton-loaders/mat-list-skeleton-loader/mat-list-skeleton-loader.component'; import { TextLineSkeletonLoaderComponent } from './helpers/skeleton-loaders/text-line-skeleton-loader/text-line-skeleton-loader.component'; +import { CreatePluginComponent } from './plugins/store/create-plugin/create-plugin.component'; +import { EditPluginComponent } from './plugins/store/edit-plugin/edit-plugin.component'; +import { PluginDetailsComponent } from './plugins/store/plugin-detail/plugin-details.component'; +import { PluginStoreOverviewComponent } from './plugins/store/plugin-store-overview/plugin-store-overview.component'; +import { PluginWrapperComponent } from './plugins/store/plugin-wrapper/plugin-wrapper.component'; import { CreateProjectComponent } from './projects/create-project/create-project.component'; -import { CreateBackupComponent } from './projects/models/backup-settings/create-backup/create-backup.component'; +import { CreatePipelineComponent } from './projects/models/backup-settings/create-pipeline/create-pipeline.component'; +import { PipelineEnvironmentInputComponent } from './projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component'; +import { PipelineGitInputComponent } from './projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component'; +import { PipelineT4CInputComponent } from './projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component'; +import { PipelineTriggersComponent } from './projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component'; import { JobRunOverviewComponent } from './projects/models/backup-settings/job-run-overview/job-run-overview.component'; import { PipelineRunWrapperComponent } from './projects/models/backup-settings/pipeline-runs/wrapper/pipeline-run-wrapper/pipeline-run-wrapper.component'; import { TriggerPipelineComponent } from './projects/models/backup-settings/trigger-pipeline/trigger-pipeline.component'; @@ -154,10 +163,11 @@ import { SettingsComponent } from './settings/settings.component'; ChooseSourceComponent, ConfirmationDialogComponent, ConnectionDialogComponent, - CreateBackupComponent, CreateModelBaseComponent, CreateModelComponent, CreatePersistentSessionComponent, + CreatePipelineComponent, + CreatePluginComponent, CreateProjectComponent, CreateReadonlyModelOptionsComponent, CreateReadonlySessionComponent, @@ -167,6 +177,7 @@ import { SettingsComponent } from './settings/settings.component'; DeleteSessionDialogComponent, DisplayValueComponent, EditGitSettingsComponent, + EditPluginComponent, EditProjectMetadataComponent, EditT4CInstanceComponent, EventsComponent, @@ -200,9 +211,15 @@ import { SettingsComponent } from './settings/settings.component'; MoveModelComponent, NavBarMenuComponent, NoticeComponent, + PipelineEnvironmentInputComponent, + PipelineGitInputComponent, PipelineRunWrapperComponent, PipelinesOverviewComponent, + PipelineT4CInputComponent, PipelineWrapperComponent, + PluginDetailsComponent, + PluginStoreOverviewComponent, + PluginWrapperComponent, ProjectAuditLogComponent, ProjectDetailsComponent, ProjectMetadataComponent, @@ -217,6 +234,7 @@ import { SettingsComponent } from './settings/settings.component'; T4CInstanceSettingsComponent, T4CModelWrapperComponent, T4CRepoDeletionDialogComponent, + PipelineTriggersComponent, T4CSettingsComponent, T4CSettingsWrapperComponent, TextLineSkeletonLoaderComponent, diff --git a/frontend/src/app/general/nav-bar/nav-bar.service.ts b/frontend/src/app/general/nav-bar/nav-bar.service.ts index 3b7bc9687..62f7043c2 100644 --- a/frontend/src/app/general/nav-bar/nav-bar.service.ts +++ b/frontend/src/app/general/nav-bar/nav-bar.service.ts @@ -38,6 +38,11 @@ export class NavBarService { routerLink: ['/sessions', 'overview'], requiredRole: 'administrator', }, + { + name: 'Plugins', + routerLink: ['/plugins'], + requiredRole: 'administrator', + }, { name: 'Prometheus', href: '/prometheus/graph', diff --git a/frontend/src/app/plugins/store/create-plugin/create-plugin.component.spec.ts b/frontend/src/app/plugins/store/create-plugin/create-plugin.component.spec.ts new file mode 100644 index 000000000..4b82e3a5c --- /dev/null +++ b/frontend/src/app/plugins/store/create-plugin/create-plugin.component.spec.ts @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreatePluginComponent } from './create-plugin.component'; + +describe('CreatePluginComponent', () => { + let component: CreatePluginComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [CreatePluginComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(CreatePluginComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/plugins/store/create-plugin/create-plugin.component.ts b/frontend/src/app/plugins/store/create-plugin/create-plugin.component.ts new file mode 100644 index 000000000..61626bbdb --- /dev/null +++ b/frontend/src/app/plugins/store/create-plugin/create-plugin.component.ts @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component } from '@angular/core'; +import { FormControl, FormGroup, Validators } from '@angular/forms'; +import { UntilDestroy } from '@ngneat/until-destroy'; +import { EditPluginComponent } from 'src/app/plugins/store/edit-plugin/edit-plugin.component'; + +@UntilDestroy() +@Component({ + selector: 'app-create-plugin', + templateUrl: '../edit-plugin/edit-plugin.component.html', + styleUrls: ['../edit-plugin/edit-plugin.component.css'], +}) +export class CreatePluginComponent extends EditPluginComponent { + editPluginForm = new FormGroup({ + remote: new FormControl('', Validators.required), + username: new FormControl(''), + password: new FormControl(''), + }); +} diff --git a/frontend/src/app/projects/models/backup-settings/create-backup/create-backup.component.css b/frontend/src/app/plugins/store/edit-plugin/edit-plugin.component.css similarity index 100% rename from frontend/src/app/projects/models/backup-settings/create-backup/create-backup.component.css rename to frontend/src/app/plugins/store/edit-plugin/edit-plugin.component.css diff --git a/frontend/src/app/plugins/store/edit-plugin/edit-plugin.component.html b/frontend/src/app/plugins/store/edit-plugin/edit-plugin.component.html new file mode 100644 index 000000000..be090f473 --- /dev/null +++ b/frontend/src/app/plugins/store/edit-plugin/edit-plugin.component.html @@ -0,0 +1,75 @@ + + + +
+ Direct URL to a raw `mbse-works-plugin.yml`: +
+ + Remote URL + + + The remote URL is required. + + +
+ Basic authentication to fetch template.
+
+
+ + Username (optional) + + + + Password (optional) + + +
+
+ + +
+
+
+
+ +
+
Template preview (not submitted)
+
+
{{
+        this.peekContent
+      }}
+
Loading...
+
+ Invalid YAML or invalid URL. Check your provided URL, it should link to + raw content of a YAML template. + This is an example. +
+
+
+
diff --git a/frontend/src/app/plugins/store/edit-plugin/edit-plugin.component.ts b/frontend/src/app/plugins/store/edit-plugin/edit-plugin.component.ts new file mode 100644 index 000000000..fe0da068c --- /dev/null +++ b/frontend/src/app/plugins/store/edit-plugin/edit-plugin.component.ts @@ -0,0 +1,83 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component } from '@angular/core'; +import { FormControl, Validators, FormGroup } from '@angular/forms'; +import { Router } from '@angular/router'; +import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; +import { debounceTime } from 'rxjs'; +import { + PluginStoreService, + Plugin, + PluginTemplateContent, +} from 'src/app/plugins/store/service/plugin-store.service'; +import { stringify } from 'yaml'; + +@UntilDestroy() +@Component({ + selector: 'app-edit-plugin', + templateUrl: './edit-plugin.component.html', + styleUrls: ['./edit-plugin.component.css'], +}) +export class EditPluginComponent { + peekContent = ''; + loadingPeekContent = true; + + pluginDeletionPossible = false; + + constructor( + public pluginStoreService: PluginStoreService, + public router: Router, + ) {} + + editPluginForm = new FormGroup({ + remote: new FormControl('', Validators.required), + username: new FormControl(''), + password: new FormControl(''), + }); + + ngOnInit(): void { + this.editPluginForm.controls['remote'].valueChanges + .pipe(debounceTime(500), untilDestroyed(this)) + .subscribe(() => { + this.refreshPluginContent(); + }); + } + + onSubmit() { + if (this.editPluginForm.valid) { + this.pluginStoreService + .registerPluginInStore(this.editPluginForm.value as Plugin) + .subscribe(() => { + this.pluginStoreService.fetchPluginsFromStore(); + this.router.navigate(['/plugins']); + }); + } + } + + refreshPluginContent() { + this.loadingPeekContent = true; + this.pluginStoreService + .fetchPluginContentFromRemote(this.editPluginForm.value as Plugin) + .pipe(untilDestroyed(this)) + .subscribe({ + next: (plugin) => { + this.peekContent = this.prettifyYAML(plugin.content); + }, + complete: () => { + this.loadingPeekContent = false; + }, + }); + } + + prettifyYAML(content: PluginTemplateContent | undefined): string { + if (content === undefined) return ''; + return stringify(content); + } + + deletePlugin() { + console.error('Not implemented, only available in PlugingDetailsComponent'); + } +} diff --git a/frontend/src/app/plugins/store/plugin-detail/plugin-details.component.ts b/frontend/src/app/plugins/store/plugin-detail/plugin-details.component.ts new file mode 100644 index 000000000..a35c815bb --- /dev/null +++ b/frontend/src/app/plugins/store/plugin-detail/plugin-details.component.ts @@ -0,0 +1,82 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { Router } from '@angular/router'; +import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; +import { filter, take } from 'rxjs'; +import { ConfirmationDialogComponent } from 'src/app/helpers/confirmation-dialog/confirmation-dialog.component'; +import { ToastService } from 'src/app/helpers/toast/toast.service'; +import { EditPluginComponent } from 'src/app/plugins/store/edit-plugin/edit-plugin.component'; +import { Plugin, PluginStoreService } from '../service/plugin-store.service'; + +@UntilDestroy() +@Component({ + selector: 'app-plugin-details', + templateUrl: '../edit-plugin/edit-plugin.component.html', + styleUrls: ['../edit-plugin/edit-plugin.component.css'], +}) +export class PluginDetailsComponent extends EditPluginComponent { + pluginDeletionPossible = true; + plugin?: Plugin = undefined; + + constructor( + pluginStoreService: PluginStoreService, + router: Router, + private toastService: ToastService, + private dialog: MatDialog, + ) { + super(pluginStoreService, router); + } + + ngOnInit(): void { + this.pluginStoreService.plugin + .pipe(untilDestroyed(this), filter(Boolean)) + .subscribe((plugin) => { + this.plugin = plugin; + this.editPluginForm.patchValue(plugin); + }); + super.ngOnInit(); + } + + onSubmit() { + if (this.editPluginForm.valid) { + this.pluginStoreService + .updatePlugin(this.plugin!.id, this.editPluginForm.value as Plugin) + .subscribe(() => { + this.toastService.showSuccess( + 'Plugin updated successfully', + `The plugin '${this.plugin?.content?.metadata?.id}' was updated successfully.`, + ); + }); + } + } + + deletePlugin() { + this.pluginStoreService.plugin + .pipe(filter(Boolean), take(1)) + .subscribe((plugin) => { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + data: { + title: 'Remove plugin', + text: 'Do you really want to delete the plugin? All related pipelines in projects will be removed.', + requiredInput: plugin?.content?.metadata?.id, + }, + }); + dialogRef.afterClosed().subscribe((selection: boolean) => { + if (!selection) return; + this.pluginStoreService.deletePlugin(plugin.id).subscribe(() => { + this.router.navigate(['/plugins']); + this.pluginStoreService.fetchPluginsFromStore(); + this.toastService.showSuccess( + 'Plugin deleted successfully', + `The plugin ${plugin.content?.metadata?.id} was deleted successfully.`, + ); + }); + }); + }); + } +} diff --git a/frontend/src/app/plugins/store/plugin-store-overview/plugin-store-overview.component.css b/frontend/src/app/plugins/store/plugin-store-overview/plugin-store-overview.component.css new file mode 100644 index 000000000..e27e1f53d --- /dev/null +++ b/frontend/src/app/plugins/store/plugin-store-overview/plugin-store-overview.component.css @@ -0,0 +1,8 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +app-mat-card-overview-skeleton-loader { + display: contents; +} diff --git a/frontend/src/app/plugins/store/plugin-store-overview/plugin-store-overview.component.html b/frontend/src/app/plugins/store/plugin-store-overview/plugin-store-overview.component.html new file mode 100644 index 000000000..2233aed2f --- /dev/null +++ b/frontend/src/app/plugins/store/plugin-store-overview/plugin-store-overview.component.html @@ -0,0 +1,43 @@ + + + diff --git a/frontend/src/app/plugins/store/plugin-store-overview/plugin-store-overview.component.ts b/frontend/src/app/plugins/store/plugin-store-overview/plugin-store-overview.component.ts new file mode 100644 index 000000000..696f079f8 --- /dev/null +++ b/frontend/src/app/plugins/store/plugin-store-overview/plugin-store-overview.component.ts @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component } from '@angular/core'; +import { PluginStoreService } from 'src/app/plugins/store/service/plugin-store.service'; + +@Component({ + selector: 'app-plugin-store-overview', + templateUrl: './plugin-store-overview.component.html', + styleUrls: ['./plugin-store-overview.component.css'], +}) +export class PluginStoreOverviewComponent { + constructor(public pluginStoreService: PluginStoreService) {} +} diff --git a/frontend/src/app/plugins/store/plugin-wrapper/plugin-wrapper.component.css b/frontend/src/app/plugins/store/plugin-wrapper/plugin-wrapper.component.css new file mode 100644 index 000000000..d49deaffd --- /dev/null +++ b/frontend/src/app/plugins/store/plugin-wrapper/plugin-wrapper.component.css @@ -0,0 +1,4 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ diff --git a/frontend/src/app/plugins/store/plugin-wrapper/plugin-wrapper.component.html b/frontend/src/app/plugins/store/plugin-wrapper/plugin-wrapper.component.html new file mode 100644 index 000000000..0b92a4b39 --- /dev/null +++ b/frontend/src/app/plugins/store/plugin-wrapper/plugin-wrapper.component.html @@ -0,0 +1,6 @@ + + + diff --git a/frontend/src/app/plugins/store/plugin-wrapper/plugin-wrapper.component.ts b/frontend/src/app/plugins/store/plugin-wrapper/plugin-wrapper.component.ts new file mode 100644 index 000000000..f46e11896 --- /dev/null +++ b/frontend/src/app/plugins/store/plugin-wrapper/plugin-wrapper.component.ts @@ -0,0 +1,49 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; +import { map } from 'rxjs'; +import { BreadcrumbsService } from 'src/app/general/breadcrumbs/breadcrumbs.service'; +import { PluginStoreService } from '../service/plugin-store.service'; + +@UntilDestroy() +@Component({ + selector: 'app-plugin-wrapper', + templateUrl: './plugin-wrapper.component.html', + styleUrls: ['./plugin-wrapper.component.css'], +}) +export class PluginWrapperComponent implements OnInit, OnDestroy { + constructor( + private route: ActivatedRoute, + public pluginStoreService: PluginStoreService, + private breadcrumbsService: BreadcrumbsService, + ) {} + + ngOnInit(): void { + this.route.params + .pipe( + map((params) => params.plugin), + untilDestroyed(this), + ) + .subscribe((pluginId: number) => { + this.pluginStoreService.fetchPluginFromStoreById(pluginId); + }); + + this.pluginStoreService.plugin + .pipe(untilDestroyed(this)) + .subscribe((plugin) => + this.breadcrumbsService.updatePlaceholder({ plugin }), + ); + } + + ngOnDestroy(): void { + this.pluginStoreService.clearPlugin(); + this.breadcrumbsService.updatePlaceholder({ + plugin: undefined, + }); + } +} diff --git a/frontend/src/app/plugins/store/service/plugin-store.service.ts b/frontend/src/app/plugins/store/service/plugin-store.service.ts new file mode 100644 index 000000000..b9550c898 --- /dev/null +++ b/frontend/src/app/plugins/store/service/plugin-store.service.ts @@ -0,0 +1,138 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { HttpClient, HttpContext } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable, tap, catchError, of } from 'rxjs'; +import { SKIP_ERROR_HANDLING } from 'src/app/general/error-handling/error-handling.interceptor'; +import { environment } from 'src/environments/environment'; + +@Injectable({ + providedIn: 'root', +}) +export class PluginStoreService { + BACKEND_URL_PREFIX = environment.backend_url + '/plugins'; + + constructor(private httpClient: HttpClient) { + this.fetchPluginsFromStore(); + } + + _plugins = new BehaviorSubject(undefined); + readonly plugins = this._plugins.asObservable(); + + _plugin = new BehaviorSubject(undefined); + readonly plugin = this._plugin.asObservable(); + + updatePlugin(pluginId: number, plugin: CreatePlugin): Observable { + return this.httpClient + .patch(`${this.BACKEND_URL_PREFIX}/${pluginId}`, plugin) + .pipe( + tap({ + next: (plugin) => { + this.fetchPluginsFromStore(); + this._plugin.next(plugin); + }, + error: () => this._plugin.next(undefined), + }), + ); + } + + deletePlugin(pluginId: number): Observable { + return this.httpClient + .delete(`${this.BACKEND_URL_PREFIX}/${pluginId}`) + .pipe( + tap(() => { + this.fetchPluginsFromStore(); + this._plugin.next(undefined); + }), + ); + } + + fetchPluginsFromStore() { + this._plugins.next(undefined); + this.httpClient + .get(`${environment.backend_url}/plugins`) + .subscribe({ next: (plugins) => this._plugins.next(plugins) }); + } + + fetchPluginFromStoreById(id: number) { + this.httpClient.get(`${this.BACKEND_URL_PREFIX}/${id}`).subscribe({ + next: (plugin) => this._plugin.next(plugin), + error: () => this._plugin.next(undefined), + }); + } + + fetchPluginContentFromRemote(plugin: Plugin): Observable { + return this.httpClient + .post(`${this.BACKEND_URL_PREFIX}/peek-plugin-content`, plugin, { + context: new HttpContext().set(SKIP_ERROR_HANDLING, true), + }) + .pipe( + tap((fplugin) => { + return fplugin; + }), + catchError((error) => { + console.error('Error fetching plugin content:', error); + return of({} as Plugin); + }), + ); + } + + registerPluginInStore(plugin: Plugin): Observable { + this._plugin.next(undefined); + return this.httpClient + .post(`${environment.backend_url}/plugins`, plugin) + .pipe(tap({ next: (plugin) => this._plugin.next(plugin) })); + } + + clearPlugin(): void { + this._plugin.next(undefined); + } +} + +export type PluginMetadata = { + id: string; + description: string; + displayName: string; + documentationURL: string; +}; + +export type CreatePlugin = { + remote: string; + username: string; + password: string; +}; + +export type Plugin = CreatePlugin & { + id: number; + content?: PluginTemplateContent; +}; + +export type PluginTemplateContent = { + trigger: PluginTrigger; + metadata?: PluginMetadata; + input?: PluginTemplateInput[]; +}; + +export type PluginTrigger = { + cron?: string; + manual?: boolean; +}; + +export type PluginTemplateInput = { + type: 'git' | 't4c' | 'environment'; +}; + +export type PluginTemplateEnvironmentMapping = { + type: 'environment'; + key: string; +}; + +export type PluginTemplateGitMapping = { + url: PluginTemplateEnvironmentMapping; + username: PluginTemplateEnvironmentMapping; + password: PluginTemplateEnvironmentMapping; + revision: PluginTemplateEnvironmentMapping; +}; diff --git a/frontend/src/app/projects/models/backup-settings/create-backup/create-backup.component.html b/frontend/src/app/projects/models/backup-settings/create-backup/create-backup.component.html deleted file mode 100644 index 5d9d07867..000000000 --- a/frontend/src/app/projects/models/backup-settings/create-backup/create-backup.component.html +++ /dev/null @@ -1,73 +0,0 @@ - - -
-

Create a new backup pipeline

-
-
- - Please select a T4C model: - - -
TeamForCapella model '{{ t4cModel.name }}'
-
- repository '{{ t4cModel.repository.name }}', instance '{{ - t4cModel.repository.instance.name - }}' -
-
-
-
- arrow_right_alt - - Please select a Git model: - - -
Git model {{ gitModel.id }}
-
- URL '{{ gitModel.path }}', revision '{{ gitModel.revision }}' -
-
-
-
-
-
-
Please specify the configuration for your backup job:
- - Run nightly (at 3 am)
- Include commit history -
- - -
- Please add a T4C model and Git model first! -
- -
- - -
-
diff --git a/frontend/src/app/projects/models/backup-settings/create-backup/create-backup.component.ts b/frontend/src/app/projects/models/backup-settings/create-backup/create-backup.component.ts deleted file mode 100644 index 6ebf25fef..000000000 --- a/frontend/src/app/projects/models/backup-settings/create-backup/create-backup.component.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* - * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { Component, Inject, OnInit } from '@angular/core'; -import { - AbstractControl, - FormControl, - FormGroup, - ValidationErrors, - ValidatorFn, -} from '@angular/forms'; -import { - MatDialogRef as MatDialogRef, - MAT_DIALOG_DATA, -} from '@angular/material/dialog'; -import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; -import { combineLatest } from 'rxjs'; -import { - PipelineService, - PostPipeline, -} from 'src/app/projects/models/backup-settings/service/pipeline.service'; -import { T4CModelService } from 'src/app/projects/models/model-source/t4c/service/t4c-model.service'; -import { GitModelService } from 'src/app/projects/project-detail/model-overview/model-detail/git-model.service'; - -@UntilDestroy() -@Component({ - selector: 'app-create-backup', - templateUrl: './create-backup.component.html', - styleUrls: ['./create-backup.component.css'], -}) -export class CreateBackupComponent implements OnInit { - t4cAndGitModelExists = false; - - constructor( - public gitModelService: GitModelService, - public t4cModelService: T4CModelService, - @Inject(MAT_DIALOG_DATA) - public data: { projectSlug: string; modelSlug: string }, - private pipelineService: PipelineService, - private dialogRef: MatDialogRef, - ) {} - - ngOnInit(): void { - this.t4cModelService.loadT4CModels( - this.data.projectSlug, - this.data.modelSlug, - ); - - this.gitModelService.loadGitModels( - this.data.projectSlug, - this.data.modelSlug, - ); - - combineLatest([ - this.gitModelService.gitModels$, - this.t4cModelService.t4cModels$, - ]) - .pipe(untilDestroyed(this)) - .subscribe( - ([gitModels, t4cModels]) => - (this.t4cAndGitModelExists = !!( - gitModels?.length && t4cModels?.length - )), - ); - } - - createBackupForm = new FormGroup({ - gitmodel: new FormControl([], [this.listNotEmptyValidator()]), - t4cmodel: new FormControl([], [this.listNotEmptyValidator()]), - configuration: new FormGroup({ - includeCommitHistory: new FormControl(false), - runNightly: new FormControl(true), - }), - }); - - listNotEmptyValidator(): ValidatorFn { - return (control: AbstractControl): ValidationErrors | null => { - if (!control.value.length) { - return { listNotEmpty: true }; - } - return null; - }; - } - - createGitBackup() { - if (this.createBackupForm.valid) { - const formValue = this.createBackupForm.value; - const createBackupformValue: PostPipeline = { - gitmodelId: formValue.gitmodel![0], - t4cmodelId: formValue.t4cmodel![0], - includeCommitHistory: formValue.configuration!.includeCommitHistory!, - runNightly: formValue.configuration!.runNightly!, - }; - this.pipelineService - .createPipeline( - this.data.projectSlug, - this.data.modelSlug, - createBackupformValue as PostPipeline, - ) - .subscribe(() => { - this.dialogRef.close(true); - }); - } - } -} diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/create-pipeline.component.css b/frontend/src/app/projects/models/backup-settings/create-pipeline/create-pipeline.component.css new file mode 100644 index 000000000..072d1e690 --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/create-pipeline.component.css @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +.header { + background-color: var(--primary-color); + color: white; + border-radius: 5px 5px 0 0; + display: flex; + justify-content: space-between; + align-items: center; +} diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/create-pipeline.component.html b/frontend/src/app/projects/models/backup-settings/create-pipeline/create-pipeline.component.html new file mode 100644 index 000000000..0735e4eb0 --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/create-pipeline.component.html @@ -0,0 +1,210 @@ + + +Selected plugin:
+ + {{ + selectedPlugin.content?.metadata?.displayName || + selectedPlugin.content?.metadata?.id + }} + +
+ + +

Welcome to the pipeline setup agent!

+ We'll guide you through the steps to set up a model modifier or model + derivative pipeline. The steps are: +
    +
  1. Select a plugin from our plugin store.
  2. +
  3. + If the selected plugin needs input values, they have to be configured in + the seconds step. +
  4. +
  5. Configure the trigger rules. When should the job run?
  6. +
  7. + In the last step, you can review the job configuration and submit it. +
  8. +
+ +
+ Introduction +
+ +
+
+
+ +
+ There are no plugins registered in the plugins store. Please contact your + administrator. +
+
+ + +
+
+
+ {{ + plugin.content?.metadata?.displayName || + "No display name provided in template" + }} +
+
+ {{ + plugin.content?.metadata?.description || + "No description provided." + }} +
+ + Requires: +
+ No input values required. +
+
    +
  • + {{ mapInputToDisplayName(inputType) }} +
  • +
+
+
+
+
+ +
+ +
+
+
+
+
+ Plugin selection +
+
+ +
+
This plugin doesn't require any additional input values.
+
+ +
+
+
+ Configuration + + + + {{ + mapInputToDisplayName(input.type) + }} + + + + + +
+ +
+ +
+ Triggers +
+ +
+ +
+ Review & confirmation + The following information will be transmitted: + +
{{ prettifyYAML(requestBody) }}
+ +
+ +
+
+
+
diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/create-pipeline.component.ts b/frontend/src/app/projects/models/backup-settings/create-pipeline/create-pipeline.component.ts new file mode 100644 index 000000000..01713effe --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/create-pipeline.component.ts @@ -0,0 +1,91 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component } from '@angular/core'; +import { MatStepper } from '@angular/material/stepper'; +import { + PluginStoreService, + Plugin, + PluginTemplateInput, + PluginTrigger, +} from 'src/app/plugins/store/service/plugin-store.service'; +import { PipelineEnvironmentInput } from 'src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component'; +import { PipelineGitInput } from 'src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component'; +import { PipelineT4CInput } from 'src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component'; +import { stringify } from 'yaml'; + +@Component({ + selector: 'app-create-pipeline', + templateUrl: './create-pipeline.component.html', + styleUrls: ['./create-pipeline.component.css'], +}) +export class CreatePipelineComponent { + constructor(public pluginStoreService: PluginStoreService) {} + + selectedPlugin?: Plugin = undefined; + + requestBody: PostPipeline = { + plugin_id: undefined, + inputs: [], + triggers: {}, + }; + + cleanInputTypes(inputs: PluginTemplateInput[]): string[] { + return [...new Set(inputs.map((input) => input.type))]; + } + + mapInputToDisplayName(input: string) { + return { + git: 'Git repository access', + t4c: 'TeamForCapella repository access', + yml: 'YAML configuration file', + environment: 'Environment variables', + }[input]; + } + + selectPlugin(stepper: MatStepper, plugin: Plugin) { + this.requestBody['plugin_id'] = plugin.id; + this.selectedPlugin = plugin; + this.stepNext(stepper); + } + + stepNext(stepper: MatStepper) { + if (stepper.selected) stepper.selected.completed = true; + stepper.next(); + } + + receivedInput( + stepper: MatStepper, + configurationStepper: MatStepper, + inputValue: any, + ): void { + this.requestBody['inputs'][configurationStepper.selectedIndex] = inputValue; + if ( + configurationStepper.selectedIndex === + configurationStepper.steps.length - 1 + ) { + this.stepNext(stepper); + } else { + this.stepNext(configurationStepper); + } + } + + receivedTrigger(stepper: MatStepper, value: any): void { + this.requestBody['triggers'] = value; + + this.stepNext(stepper); + } + + prettifyYAML(content: any): string { + if (content === undefined) return ''; + return stringify(content); + } +} + +type PostPipeline = { + plugin_id?: number; + inputs: (PipelineGitInput | PipelineT4CInput | PipelineEnvironmentInput)[]; + triggers?: PluginTrigger; +}; diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.css b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.css new file mode 100644 index 000000000..d49deaffd --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.css @@ -0,0 +1,4 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.html b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.html new file mode 100644 index 000000000..48cc47ba5 --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.html @@ -0,0 +1,33 @@ + + +
+
{{ variable.description }}
+
+
+ {{ + variable.displayName + }} +
+
+ + {{ variable.displayName }} + + + {{ value }} + + + + +
+
+
+
+ +
+ +
diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.spec.ts b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.spec.ts new file mode 100644 index 000000000..3c50d800f --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PipelineEnvironmentInputComponent } from './pipeline-environment-input.component'; + +describe('PipelineEnvironmentInputComponent', () => { + let component: PipelineEnvironmentInputComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [PipelineEnvironmentInputComponent], + }); + fixture = TestBed.createComponent(PipelineEnvironmentInputComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.ts b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.ts new file mode 100644 index 000000000..a6e2cccf7 --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-environment-input/pipeline-environment-input.component.ts @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { FormControl, FormGroup } from '@angular/forms'; +import { PluginTemplateInput } from 'src/app/plugins/store/service/plugin-store.service'; + +@Component({ + selector: 'app-pipeline-environment-input', + templateUrl: './pipeline-environment-input.component.html', + styleUrls: ['./pipeline-environment-input.component.css'], +}) +export class PipelineEnvironmentInputComponent { + form: FormGroup = new FormGroup({}); + + environmentInput?: PluginTemplateEnvironmentInput = undefined; + + @Input() + set input(input: PluginTemplateInput) { + this.environmentInput = input as PluginTemplateEnvironmentInput; + this.environmentInput.variables.forEach((variable) => { + this.form.addControl(variable.key, new FormControl(variable.default)); + }); + } + + @Output() + inputFinished = new EventEmitter(); + + submitInput() { + this.inputFinished.emit(this.form.value); + } +} + +export type PluginTemplateEnvironmentInput = PluginTemplateInput & { + variables: EnvironmentVariable[]; +}; + +type EnvironmentVariable = { + key: string; + type: 'dropdown' | 'boolean'; + displayName: string; + values: string[]; + description: string; + default: string | boolean; +}; + +export type PipelineEnvironmentInput = { + [key: string]: string; +}; diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.css b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.css new file mode 100644 index 000000000..d49deaffd --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.css @@ -0,0 +1,4 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.html b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.html new file mode 100644 index 000000000..40683dc7e --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.html @@ -0,0 +1,53 @@ + + +{{ gitInput.description }} +
+ No Git repositories found for this model. Please link a Git repository first. +
+ +
+ +
+ + + +
Git model {{ gitModel.id }}
+
+ URL '{{ gitModel.path }}', revision '{{ gitModel.revision }}' +
+
+
+ +
+ The pipeline will get access to the following information of the selected Git + model: +
    +
  • + {{ mapping.key }} +
  • +
+ Changes in the Git model will be propagated to the pipeline. +
+ +
+ +
diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.spec.ts b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.spec.ts new file mode 100644 index 000000000..d39392218 --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PipelineGitInputComponent } from './pipeline-git-input.component'; + +describe('PipelineGitInputComponent', () => { + let component: PipelineGitInputComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [PipelineGitInputComponent], + }); + fixture = TestBed.createComponent(PipelineGitInputComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.ts b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.ts new file mode 100644 index 000000000..c12b7c3a9 --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-git-input/pipeline-git-input.component.ts @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; +import { combineLatest, filter } from 'rxjs'; +import { PluginTemplateInput } from 'src/app/plugins/store/service/plugin-store.service'; +import { ModelService } from 'src/app/projects/models/service/model.service'; +import { GitModelService } from 'src/app/projects/project-detail/model-overview/model-detail/git-model.service'; +import { ProjectService } from 'src/app/projects/service/project.service'; + +@Component({ + selector: 'app-pipeline-git-input', + templateUrl: './pipeline-git-input.component.html', + styleUrls: ['./pipeline-git-input.component.css'], +}) +@UntilDestroy() +export class PipelineGitInputComponent { + @Input() + input?: PluginTemplateInput = undefined; + + selectedGitModelIDs?: number[] = undefined; + + @Output() + inputFinished = new EventEmitter(); + + get gitInput() { + return this.input as PluginTemplateGitInput; + } + + constructor( + public gitModelService: GitModelService, + private projectService: ProjectService, + private modelService: ModelService, + ) { + combineLatest([ + this.projectService.project$.pipe(filter(Boolean)), + this.modelService.model$.pipe(filter(Boolean)), + ]) + .pipe(untilDestroyed(this)) + .subscribe(([project, model]) => { + this.gitModelService.loadGitModels(project.slug, model.slug); + }); + } + + submitGitModel() { + this.inputFinished.emit({ git_model_id: this.selectedGitModelIDs![0] }); + } +} + +export type GitModelInput = { + git_model_id: number; +}; + +export type PluginTemplateGitInput = PluginTemplateInput & { + mapping: string; + description: string; +}; + +export type PipelineGitInput = { + git_model_id: number; +}; diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.css b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.css new file mode 100644 index 000000000..d49deaffd --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.css @@ -0,0 +1,4 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.html b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.html new file mode 100644 index 000000000..ec513a2ab --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.html @@ -0,0 +1,56 @@ + + +{{ t4cInput.description }} +
+ No TeamForCapella repositories/projects found for this model. Please link a + T4C repository/project first. +
+ +
+ +
+ + + +
T4C model {{ t4cModel.id }}
+
+ Server '{{ t4cModel.repository.instance.name }}', Repository '{{ + t4cModel.repository.name + }}', Project '{{ t4cModel.name }}' +
+
+
+ +
+ A technical user will be created for this pipeline. The technical user will + get access to the selected TeamForCapella repository. THe following + information is available for the pipeline: +
    +
  • + {{ mapping.key }} +
  • +
+
+ +
+ +
diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.spec.ts b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.spec.ts new file mode 100644 index 000000000..4840f1c6e --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PipelineT4CInputComponent } from './pipeline-t4c-input.component'; + +describe('PipelineT4cInputComponent', () => { + let component: PipelineT4CInputComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [PipelineT4CInputComponent], + }); + fixture = TestBed.createComponent(PipelineT4CInputComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.ts b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.ts new file mode 100644 index 000000000..dc4750e40 --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-input/pipeline-t4c-input/pipeline-t4c-input.component.ts @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; +import { combineLatest, filter } from 'rxjs'; +import { PluginTemplateInput } from 'src/app/plugins/store/service/plugin-store.service'; +import { T4CModelService } from 'src/app/projects/models/model-source/t4c/service/t4c-model.service'; +import { ModelService } from 'src/app/projects/models/service/model.service'; +import { ProjectService } from 'src/app/projects/service/project.service'; + +@Component({ + selector: 'app-pipeline-t4c-input', + templateUrl: './pipeline-t4c-input.component.html', + styleUrls: ['./pipeline-t4c-input.component.css'], +}) +@UntilDestroy() +export class PipelineT4CInputComponent { + @Input() + input?: PluginTemplateInput = undefined; + + selectedT4CModelIDs?: number[] = undefined; + + @Output() + inputFinished = new EventEmitter(); + + get t4cInput() { + return this.input as PluginTemplateT4CInput; + } + + constructor( + public t4cModelService: T4CModelService, + private projectService: ProjectService, + private modelService: ModelService, + ) { + combineLatest([ + this.projectService.project$.pipe(filter(Boolean)), + this.modelService.model$.pipe(filter(Boolean)), + ]) + .pipe(untilDestroyed(this)) + .subscribe(([project, model]) => { + this.t4cModelService.loadT4CModels(project.slug, model.slug); + }); + } + + submitGitModel() { + this.inputFinished.emit({ t4c_model_id: this.selectedT4CModelIDs![0] }); + } +} + +export type T4CModelInput = { + t4c_model_id: number; +}; + +export type PluginTemplateT4CInput = PluginTemplateInput & { + mapping: string; + description: string; +}; + +export type PipelineT4CInput = { + t4c_model_id: number; +}; diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.css b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.css new file mode 100644 index 000000000..d49deaffd --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.css @@ -0,0 +1,4 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.html b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.html new file mode 100644 index 000000000..319467540 --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.html @@ -0,0 +1,33 @@ + + +Please select when you'd like to run the pipeline: + +
+
+ Allow manual pipeline triggers +
+
+ Run {{ humanFriendlyCron(pipelineTrigger!.cron!) }} +
+
+ + + +
+ +
diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.spec.ts b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.spec.ts new file mode 100644 index 000000000..58b88ab3c --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PipelineTriggersComponent } from './pipeline-triggers.component'; + +describe('PipelineTriggersComponent', () => { + let component: PipelineTriggersComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [PipelineTriggersComponent], + }); + fixture = TestBed.createComponent(PipelineTriggersComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.ts b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.ts new file mode 100644 index 000000000..7f1348f72 --- /dev/null +++ b/frontend/src/app/projects/models/backup-settings/create-pipeline/pipeline-triggers/pipeline-triggers.component.ts @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { FormControl, FormGroup } from '@angular/forms'; +import cronstrue from 'cronstrue'; +import { PluginTrigger } from 'src/app/plugins/store/service/plugin-store.service'; + +@Component({ + selector: 'app-pipeline-triggers', + templateUrl: './pipeline-triggers.component.html', + styleUrls: ['./pipeline-triggers.component.css'], +}) +export class PipelineTriggersComponent { + @Input() pipelineTrigger?: PluginTrigger = undefined; + + @Output() + triggersFinished = new EventEmitter(); + + formGroup = new FormGroup({ + manual: new FormControl(true), + cron: new FormControl(false), + }); + // TODO: Add validator that at least one trigger is selected + + humanFriendlyCron(cron: string) { + const uppercaseCron = cronstrue.toString(cron, { verbose: true }); + return uppercaseCron.charAt(0).toLowerCase() + uppercaseCron.slice(1); + } + + submitTriggers() { + this.triggersFinished.emit(this.formGroup.value); + } +} diff --git a/frontend/src/app/projects/models/backup-settings/service/pipeline.service.ts b/frontend/src/app/projects/models/backup-settings/service/pipeline.service.ts index f6a2c0501..04ec103c2 100644 --- a/frontend/src/app/projects/models/backup-settings/service/pipeline.service.ts +++ b/frontend/src/app/projects/models/backup-settings/service/pipeline.service.ts @@ -27,7 +27,7 @@ export class PipelineService { public readonly pipeline$ = this._pipeline.asObservable(); urlFactory(projectSlug: string, modelSlug: string): string { - return `${environment.backend_url}/projects/${projectSlug}/models/${modelSlug}/backups/pipelines`; + return `${environment.backend_url}/projects/${projectSlug}/models/${modelSlug}/pipelines`; } loadPipelines( diff --git a/frontend/src/app/projects/models/backup-settings/trigger-pipeline/trigger-pipeline.component.html b/frontend/src/app/projects/models/backup-settings/trigger-pipeline/trigger-pipeline.component.html index acaf0e211..85ea6c824 100644 --- a/frontend/src/app/projects/models/backup-settings/trigger-pipeline/trigger-pipeline.component.html +++ b/frontend/src/app/projects/models/backup-settings/trigger-pipeline/trigger-pipeline.component.html @@ -3,118 +3,117 @@ ~ SPDX-License-Identifier: Apache-2.0 --> -
-
-
- Please select the pipeline you'd like to execute or to see the logs: - - add_circle -
-
-
- + This feature is currently in the experimental phase. There are breaking + changes and bugs to be expected. +
+ +
+ + Please select the pipeline you'd like to execute or to see the logs: + + +
+
+
+
+ + Backup (ID: {{ pipeline.id }}) +
+ Runs nightly at 3am + with commit historywithout commit history - Backup (ID: {{ pipeline.id }}) -
- Runs nightly at 3am - with commit historywithout commit history - or with manual trigger - - Runs only with manual trigger -
-
- TeamForCapella
- Instance {{ pipeline.t4c_model.instance_name }},
Repository {{ pipeline.t4c_model.repository_name }},
Project: - {{ pipeline.t4c_model.project_name }}
arrow_forward - - - Git
- URL: {{ pipeline.git_model.path }},
revision: {{ pipeline.git_model.revision }},
entrypoint: - {{ pipeline.git_model.entrypoint }} -
-
-
+ or with manual trigger + + Runs only with manual trigger +
+
+ TeamForCapella
+ Instance {{ pipeline.t4c_model.instance_name }},
Repository {{ pipeline.t4c_model.repository_name }},
Project: {{ pipeline.t4c_model.project_name }}
arrow_forward + + + Git
+ URL: {{ pipeline.git_model.path }},
revision: {{ pipeline.git_model.revision }},
entrypoint: + {{ pipeline.git_model.entrypoint }} +
-
-
- No pipelines found. Please create a new pipeline. -
- -
-
-
-

Run the pipeline

- -
-
- Please select the following configuration options:
- Include commit history -

- Current estimate of the duration (according to the selected - configuration): - {{ estimateTime() }} -
+ +
+
+
+ No pipelines found. Please create a new pipeline. +
- -
- -
+
+
+
+

Run the pipeline

-
-
-

Additional actions

-
- - - View runs - - +
+ Please select the following configuration options:
+ Include commit history - Force deletion - +
+ +
+ +
+ +
+
+

Additional actions

+
+ + + View runs + + + Force deletion +
diff --git a/frontend/src/app/projects/models/backup-settings/trigger-pipeline/trigger-pipeline.component.ts b/frontend/src/app/projects/models/backup-settings/trigger-pipeline/trigger-pipeline.component.ts index d0a5a95a4..5b539e19a 100644 --- a/frontend/src/app/projects/models/backup-settings/trigger-pipeline/trigger-pipeline.component.ts +++ b/frontend/src/app/projects/models/backup-settings/trigger-pipeline/trigger-pipeline.component.ts @@ -3,27 +3,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Component, Inject, OnInit } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { FormControl, FormGroup } from '@angular/forms'; -import { - MatDialog, - MatDialogRef, - MAT_DIALOG_DATA, -} from '@angular/material/dialog'; +import { MatDialog, MatDialogRef } from '@angular/material/dialog'; import { Router } from '@angular/router'; +import { combineLatest, filter, map, switchMap, tap } from 'rxjs'; import { ToastService } from 'src/app/helpers/toast/toast.service'; import { PipelineRun, PipelineRunService, } from 'src/app/projects/models/backup-settings/pipeline-runs/service/pipeline-run.service'; +import { ModelService } from 'src/app/projects/models/service/model.service'; +import { ProjectService } from 'src/app/projects/service/project.service'; import { UserService } from 'src/app/services/user/user.service'; import { SessionService } from 'src/app/sessions/service/session.service'; -import { CreateBackupComponent } from '../create-backup/create-backup.component'; import { PipelineService, Pipeline } from '../service/pipeline.service'; -import { - ViewLogsDialogComponent, - ViewLogsData, -} from '../view-logs-dialog/view-logs-dialog.component'; @Component({ selector: 'app-trigger-pipeline', @@ -31,6 +25,9 @@ import { styleUrls: ['./trigger-pipeline.component.css'], }) export class TriggerPipelineComponent implements OnInit { + projectSlug?: string = undefined; + modelSlug?: string = undefined; + selectedPipeline?: Pipeline = undefined; force = false; @@ -42,20 +39,35 @@ export class TriggerPipelineComponent implements OnInit { constructor( private toastService: ToastService, private dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) - public data: { projectSlug: string; modelSlug: string }, public dialog: MatDialog, public pipelineService: PipelineService, private pipelineRunService: PipelineRunService, public sessionService: SessionService, public userService: UserService, + private projectService: ProjectService, + private modelService: ModelService, private router: Router, ) {} ngOnInit(): void { - this.pipelineService - .loadPipelines(this.data.projectSlug, this.data.modelSlug) - .subscribe(); + combineLatest([ + this.projectService.project$.pipe( + filter(Boolean), + map((project) => project.slug), + ), + this.modelService.model$.pipe( + filter(Boolean), + map((model) => model.slug), + ), + ]).pipe( + tap(([projectSlug, modelSlug]) => { + this.projectSlug = projectSlug; + this.modelSlug = modelSlug; + }), + switchMap(([projectSlug, modelSlug]) => + this.pipelineService.loadPipelines(projectSlug, modelSlug), + ), + ); } selectPipeline(pipeline: Pipeline) { @@ -65,8 +77,8 @@ export class TriggerPipelineComponent implements OnInit { runPipeline() { this.pipelineRunService .triggerRun( - this.data.projectSlug, - this.data.modelSlug, + this.projectSlug!, + this.modelSlug!, this.selectedPipeline!.id, this.configurationForm.value.includeHistory!, ) @@ -74,9 +86,9 @@ export class TriggerPipelineComponent implements OnInit { this.closeDialog(); this.router.navigate([ 'project', - this.data.projectSlug, + this.projectSlug, 'model', - this.data.modelSlug, + this.modelSlug, 'pipeline', this.selectedPipeline!.id, 'run', @@ -86,25 +98,13 @@ export class TriggerPipelineComponent implements OnInit { }); } - estimateTime(): string { - if (this.configurationForm.value.includeHistory) { - return '1-6 hours'; - } - return '5-10 minutes'; - } - closeDialog(): void { this.dialogRef.close(); } removePipeline(backup: Pipeline): void { this.pipelineService - .removePipeline( - this.data.projectSlug, - this.data.modelSlug, - backup.id, - this.force, - ) + .removePipeline(this.projectSlug!, this.modelSlug!, backup.id, this.force) .subscribe(() => { this.toastService.showSuccess( 'Backup pipeline deleted', @@ -118,40 +118,12 @@ export class TriggerPipelineComponent implements OnInit { this.closeDialog(); this.router.navigate([ 'project', - this.data.projectSlug, + this.projectSlug, 'model', - this.data.modelSlug, + this.modelSlug, 'pipeline', backup.id, 'runs', ]); } - - viewLogs(backup: Pipeline): void { - this.dialog.open(ViewLogsDialogComponent, { - data: { - projectSlug: this.data.projectSlug, - modelSlug: this.data.modelSlug, - job_id: 'backup.lastrun.id', - backup_id: backup.id, - } as ViewLogsData, - }); - } - - createPipeline(): void { - const dialogRef = this.dialog.open(CreateBackupComponent, { - data: { - projectSlug: this.data.projectSlug, - modelSlug: this.data.modelSlug, - }, - }); - - dialogRef.afterClosed().subscribe((success) => { - if (success) { - this.pipelineService - .loadPipelines(this.data.projectSlug, this.data.modelSlug) - .subscribe(); - } - }); - } } diff --git a/frontend/src/app/projects/project-detail/model-overview/model-overview.component.html b/frontend/src/app/projects/project-detail/model-overview/model-overview.component.html index 3998bf63f..e60996f9b 100644 --- a/frontend/src/app/projects/project-detail/model-overview/model-overview.component.html +++ b/frontend/src/app/projects/project-detail/model-overview/model-overview.component.html @@ -125,9 +125,9 @@

Models

{ - this.dialog.open(TriggerPipelineComponent, { - data: { projectSlug: project!.slug, modelSlug: model.slug }, - }); - }); - } - openDiagramsDialog(model: Model): void { this.dialog.open(ModelDiagramDialogComponent, { maxWidth: '100vw', diff --git a/frontend/src/app/projects/service/project.service.ts b/frontend/src/app/projects/service/project.service.ts index 54abdca57..2d6d3e889 100644 --- a/frontend/src/app/projects/service/project.service.ts +++ b/frontend/src/app/projects/service/project.service.ts @@ -20,7 +20,7 @@ import { environment } from 'src/environments/environment'; export class ProjectService { BACKEND_URL_PREFIX = environment.backend_url + '/projects'; - constructor(private http: HttpClient) {} + constructor(private http: HttpClient) {} // Also load all projects? private _project = new BehaviorSubject(undefined); private _projects = new BehaviorSubject(undefined); diff --git a/frontend/src/styles.css b/frontend/src/styles.css index 0c3e40df9..87b47c641 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -231,7 +231,7 @@ Angular Material Card Styles color: white; border-radius: 5px 5px 0 0; display: flex; - flex-direction: column; + flex-direction: row; padding: 10px 20px; font-size: 1.5em; }