From 6f27dc94df547a716d986db0a78d4c1be88be51e Mon Sep 17 00:00:00 2001 From: Taylor Date: Wed, 2 Oct 2024 10:50:09 -0500 Subject: [PATCH 01/42] `refactor: Update endpoint in provision.py` --- backend/app/incidents/routes/incident_report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/app/incidents/routes/incident_report.py b/backend/app/incidents/routes/incident_report.py index df4c7c53..b1acf192 100644 --- a/backend/app/incidents/routes/incident_report.py +++ b/backend/app/incidents/routes/incident_report.py @@ -129,7 +129,7 @@ async def get_cases_export_all_route( @incidents_report_router.post( - "/generate-report/{customer_code}", + "/generate-report-csv/{customer_code}", description="Generate a report for a customer", ) async def get_cases_export_customer_route( From 56946b36ae2e71f52fa6779042593d7d93786480 Mon Sep 17 00:00:00 2001 From: Taylor Date: Wed, 2 Oct 2024 11:39:29 -0500 Subject: [PATCH 02/42] `refactor: Update endpoint in provision.py` --- backend/app/customer_provisioning/services/wazuh_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/app/customer_provisioning/services/wazuh_manager.py b/backend/app/customer_provisioning/services/wazuh_manager.py index 7077355c..aa3c84c1 100644 --- a/backend/app/customer_provisioning/services/wazuh_manager.py +++ b/backend/app/customer_provisioning/services/wazuh_manager.py @@ -125,7 +125,7 @@ async def configure_wazuh_group(group_code, template_path, request: ProvisionNew # Make the API request to update the group configuration return await send_wazuh_put_request( - endpoint=f"groups/{group_code}/configuration", + endpoint=f"/groups/{group_code}/configuration", data=group_config, xml_data=True, ) From a3f51a74afbc563a65550a01de13041577a79d2d Mon Sep 17 00:00:00 2001 From: Davide Di Modica Date: Thu, 3 Oct 2024 16:10:03 +0200 Subject: [PATCH 03/42] chore: update dependencies in frontend --- frontend/package-lock.json | 114 ++++++++++++++++++------------------- frontend/package.json | 8 +-- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c2dff753..0629b3b0 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -58,7 +58,7 @@ "@types/fs-extra": "^11.0.4", "@types/inquirer": "^9.0.7", "@types/jsdom": "^21.1.7", - "@types/lodash": "^4.17.9", + "@types/lodash": "^4.17.10", "@types/node": "^22.7.4", "@types/validator": "^13.12.2", "@vitejs/plugin-vue": "^5.1.4", @@ -70,7 +70,7 @@ "eslint": "^9.11.1", "flourite": "^1.3.0", "fs-extra": "^11.2.0", - "globals": "^15.9.0", + "globals": "^15.10.0", "jsdom": "^25.0.1", "json5": "^2.2.3", "npm-run-all2": "^6.2.3", @@ -83,21 +83,21 @@ "tailwindcss": "^3.4.13", "taze": "^0.17.2", "type-fest": "^4.26.1", - "typescript": "~5.5.4", + "typescript": "^5.5.4", "unplugin-vue-components": "^0.27.4", "vite": "^5.4.8", "vite-bundle-analyzer": "^0.12.1", "vite-bundle-visualizer": "^1.2.1", "vite-plugin-vue-devtools": "^7.4.6", "vite-svg-loader": "^5.1.0", - "vitest": "^2.1.1", + "vitest": "^2.1.2", "vue-tsc": "^2.1.6" }, "engines": { "node": ">=18.0.0" }, "optionalDependencies": { - "@rollup/rollup-linux-x64-gnu": "^4.23.0" + "@rollup/rollup-linux-x64-gnu": "^4.24.0" } }, "node_modules/@ajoelp/json-to-formdata": { @@ -2350,9 +2350,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.23.0.tgz", - "integrity": "sha512-I/eXsdVoCKtSgK9OwyQKPAfricWKUMNCwJKtatRYMmDo5N859tbO3UsBw5kT3dU1n6ZcM1JDzPRSGhAUkxfLxw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", "cpu": [ "x64" ], @@ -2619,9 +2619,9 @@ "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==" }, "node_modules/@types/lodash": { - "version": "4.17.9", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.9.tgz", - "integrity": "sha512-w9iWudx1XWOHW5lQRS9iKpK/XuRhnN+0T7HvdCCd802FYkT1AMTnxndJHGrNJwRoRHkslGr4S29tjm1cT7x/7w==" + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==" }, "node_modules/@types/lodash-es": { "version": "4.17.12", @@ -3452,13 +3452,13 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.1.tgz", - "integrity": "sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.2.tgz", + "integrity": "sha512-FEgtlN8mIUSEAAnlvn7mP8vzaWhEaAEvhSXCqrsijM7K6QqjB11qoRZYEd4AKSCDz8p0/+yH5LzhZ47qt+EyPg==", "dev": true, "dependencies": { - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", + "@vitest/spy": "2.1.2", + "@vitest/utils": "2.1.2", "chai": "^5.1.1", "tinyrainbow": "^1.2.0" }, @@ -3467,9 +3467,9 @@ } }, "node_modules/@vitest/mocker": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.1.tgz", - "integrity": "sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.2.tgz", + "integrity": "sha512-ExElkCGMS13JAJy+812fw1aCv2QO/LBK6CyO4WOPAzLTmve50gydOlWhgdBJPx2ztbADUq3JVI0C5U+bShaeEA==", "dev": true, "dependencies": { "@vitest/spy": "^2.1.0-beta.1", @@ -3480,7 +3480,7 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/spy": "2.1.1", + "@vitest/spy": "2.1.2", "msw": "^2.3.5", "vite": "^5.0.0" }, @@ -3503,9 +3503,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.1.tgz", - "integrity": "sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.2.tgz", + "integrity": "sha512-FIoglbHrSUlOJPDGIrh2bjX1sNars5HbxlcsFKCtKzu4+5lpsRhOCVcuzp0fEhAGHkPZRIXVNzPcpSlkoZ3LuA==", "dev": true, "dependencies": { "tinyrainbow": "^1.2.0" @@ -3515,12 +3515,12 @@ } }, "node_modules/@vitest/runner": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.1.tgz", - "integrity": "sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.2.tgz", + "integrity": "sha512-UCsPtvluHO3u7jdoONGjOSil+uON5SSvU9buQh3lP7GgUXHp78guN1wRmZDX4wGK6J10f9NUtP6pO+SFquoMlw==", "dev": true, "dependencies": { - "@vitest/utils": "2.1.1", + "@vitest/utils": "2.1.2", "pathe": "^1.1.2" }, "funding": { @@ -3528,12 +3528,12 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.1.tgz", - "integrity": "sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.2.tgz", + "integrity": "sha512-xtAeNsZ++aRIYIUsek7VHzry/9AcxeULlegBvsdLncLmNCR6tR8SRjn8BbDP4naxtccvzTqZ+L1ltZlRCfBZFA==", "dev": true, "dependencies": { - "@vitest/pretty-format": "2.1.1", + "@vitest/pretty-format": "2.1.2", "magic-string": "^0.30.11", "pathe": "^1.1.2" }, @@ -3542,9 +3542,9 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.1.tgz", - "integrity": "sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.2.tgz", + "integrity": "sha512-GSUi5zoy+abNRJwmFhBDC0yRuVUn8WMlQscvnbbXdKLXX9dE59YbfwXxuJ/mth6eeqIzofU8BB5XDo/Ns/qK2A==", "dev": true, "dependencies": { "tinyspy": "^3.0.0" @@ -3554,12 +3554,12 @@ } }, "node_modules/@vitest/utils": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.1.tgz", - "integrity": "sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.2.tgz", + "integrity": "sha512-zMO2KdYy6mx56btx9JvAqAZ6EyS3g49krMPPrgOp1yxGZiA93HumGk+bZ5jIZtOg5/VBYl5eBmGRQHqq4FG6uQ==", "dev": true, "dependencies": { - "@vitest/pretty-format": "2.1.1", + "@vitest/pretty-format": "2.1.2", "loupe": "^3.1.1", "tinyrainbow": "^1.2.0" }, @@ -7463,9 +7463,9 @@ } }, "node_modules/globals": { - "version": "15.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", - "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", + "version": "15.10.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.10.0.tgz", + "integrity": "sha512-tqFIbz83w4Y5TCbtgjZjApohbuh7K9BxGYFm7ifwDR240tvdb7P9x+/9VvUKlmkPoiknoJtanI8UOrqxS3a7lQ==", "dev": true, "engines": { "node": ">=18" @@ -14386,9 +14386,9 @@ } }, "node_modules/vite-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.1.tgz", - "integrity": "sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.2.tgz", + "integrity": "sha512-HPcGNN5g/7I2OtPjLqgOtCRu/qhVvBxTUD3qzitmL0SrG1cWFzxzhMDWussxSbrRYWqnKf8P2jiNhPMSN+ymsQ==", "dev": true, "dependencies": { "cac": "^6.7.14", @@ -14670,18 +14670,18 @@ } }, "node_modules/vitest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.1.tgz", - "integrity": "sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.2.tgz", + "integrity": "sha512-veNjLizOMkRrJ6xxb+pvxN6/QAWg95mzcRjtmkepXdN87FNfxAss9RKe2far/G9cQpipfgP2taqg0KiWsquj8A==", "dev": true, "dependencies": { - "@vitest/expect": "2.1.1", - "@vitest/mocker": "2.1.1", - "@vitest/pretty-format": "^2.1.1", - "@vitest/runner": "2.1.1", - "@vitest/snapshot": "2.1.1", - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", + "@vitest/expect": "2.1.2", + "@vitest/mocker": "2.1.2", + "@vitest/pretty-format": "^2.1.2", + "@vitest/runner": "2.1.2", + "@vitest/snapshot": "2.1.2", + "@vitest/spy": "2.1.2", + "@vitest/utils": "2.1.2", "chai": "^5.1.1", "debug": "^4.3.6", "magic-string": "^0.30.11", @@ -14692,7 +14692,7 @@ "tinypool": "^1.0.0", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.1.1", + "vite-node": "2.1.2", "why-is-node-running": "^2.3.0" }, "bin": { @@ -14707,8 +14707,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.1", - "@vitest/ui": "2.1.1", + "@vitest/browser": "2.1.2", + "@vitest/ui": "2.1.2", "happy-dom": "*", "jsdom": "*" }, diff --git a/frontend/package.json b/frontend/package.json index 473c0b08..eaa97599 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -76,7 +76,7 @@ "vuedraggable": "^4.1.0" }, "optionalDependencies": { - "@rollup/rollup-linux-x64-gnu": "^4.23.0" + "@rollup/rollup-linux-x64-gnu": "^4.24.0" }, "devDependencies": { "@antfu/eslint-config": "^3.7.3", @@ -88,7 +88,7 @@ "@types/fs-extra": "^11.0.4", "@types/inquirer": "^9.0.7", "@types/jsdom": "^21.1.7", - "@types/lodash": "^4.17.9", + "@types/lodash": "^4.17.10", "@types/node": "^22.7.4", "@types/validator": "^13.12.2", "@vitejs/plugin-vue": "^5.1.4", @@ -100,7 +100,7 @@ "eslint": "^9.11.1", "flourite": "^1.3.0", "fs-extra": "^11.2.0", - "globals": "^15.9.0", + "globals": "^15.10.0", "jsdom": "^25.0.1", "json5": "^2.2.3", "npm-run-all2": "^6.2.3", @@ -120,7 +120,7 @@ "vite-bundle-visualizer": "^1.2.1", "vite-plugin-vue-devtools": "^7.4.6", "vite-svg-loader": "^5.1.0", - "vitest": "^2.1.1", + "vitest": "^2.1.2", "vue-tsc": "^2.1.6" }, "pnpm": { From d47d5616637dfb2b952c0a262d248ee876685110 Mon Sep 17 00:00:00 2001 From: Davide Di Modica Date: Thu, 3 Oct 2024 16:10:36 +0200 Subject: [PATCH 04/42] refactor: update case export service --- frontend/src/api/endpoints/incidentManagement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/api/endpoints/incidentManagement.ts b/frontend/src/api/endpoints/incidentManagement.ts index f8247330..bf32022b 100644 --- a/frontend/src/api/endpoints/incidentManagement.ts +++ b/frontend/src/api/endpoints/incidentManagement.ts @@ -289,7 +289,7 @@ export default { let url = `/incidents/report/generate-report` if (customerCode) { - url = `/incidents/report/generate-report/${customerCode}` + url = `/incidents/report/generate-report-csv/${customerCode}` } return HttpClient.post(url, { From 09817a483bfc7c6b67dfc1add1d1c46e96637c1b Mon Sep 17 00:00:00 2001 From: Taylor Date: Thu, 3 Oct 2024 10:20:01 -0500 Subject: [PATCH 05/42] add case report templates db table --- backend/alembic/alembic.ini | 2 +- backend/alembic/env.py | 1 + ...498_add_table_for_case_report_templates.py | 40 +++++++++++++++++++ backend/app/incidents/models.py | 14 +++++++ 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 backend/alembic/versions/a1e4beb87498_add_table_for_case_report_templates.py diff --git a/backend/alembic/alembic.ini b/backend/alembic/alembic.ini index 96b9825d..e09c09cc 100644 --- a/backend/alembic/alembic.ini +++ b/backend/alembic/alembic.ini @@ -60,7 +60,7 @@ version_path_separator = os # Use os.pathsep. Default configuration used for ne # are written from script.py.mako # output_encoding = utf-8 -sqlalchemy.url = mysql+pymysql://copilot:H7U3AHsXWSGvE5L123B7$GQdLQz@10.255.254.2/copilot +sqlalchemy.url = mysql+pymysql://copilot:REPLACE_ME@copilot-mysql/copilot [post_write_hooks] diff --git a/backend/alembic/env.py b/backend/alembic/env.py index 8e04f93f..b78f41d4 100644 --- a/backend/alembic/env.py +++ b/backend/alembic/env.py @@ -28,6 +28,7 @@ from app.incidents.models import AlertTitleFieldName from app.incidents.models import AlertToTag from app.incidents.models import Asset +from app.incidents.models import CaseReportTemplateDataStore from app.incidents.models import AssetFieldName from app.incidents.models import Case from app.incidents.models import CaseAlertLink diff --git a/backend/alembic/versions/a1e4beb87498_add_table_for_case_report_templates.py b/backend/alembic/versions/a1e4beb87498_add_table_for_case_report_templates.py new file mode 100644 index 00000000..95a5f0c7 --- /dev/null +++ b/backend/alembic/versions/a1e4beb87498_add_table_for_case_report_templates.py @@ -0,0 +1,40 @@ +"""Add table for case report templates + +Revision ID: a1e4beb87498 +Revises: ba64d98dbdc5 +Create Date: 2024-10-03 10:14:31.289126 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + +# revision identifiers, used by Alembic. +revision: str = 'a1e4beb87498' +down_revision: Union[str, None] = 'ba64d98dbdc5' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('incident_management_case_report_template_datastore', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('report_template_name', sa.String(length=255), nullable=False), + sa.Column('bucket_name', sa.String(length=255), nullable=False), + sa.Column('object_key', sa.String(length=1024), nullable=False), + sa.Column('file_name', sa.String(length=255), nullable=False), + sa.Column('content_type', sa.String(length=100), nullable=True), + sa.Column('file_size', sa.Integer(), nullable=True), + sa.Column('upload_time', sa.DateTime(), nullable=False), + sa.Column('file_hash', sa.String(length=128), nullable=False), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('incident_management_case_report_template_datastore') + # ### end Alembic commands ### diff --git a/backend/app/incidents/models.py b/backend/app/incidents/models.py index 41eb0eeb..48855512 100644 --- a/backend/app/incidents/models.py +++ b/backend/app/incidents/models.py @@ -165,3 +165,17 @@ class CaseDataStore(SQLModel, table=True): file_hash: str = Field(max_length=128, nullable=False) # Hash of the file (e.g., SHA-256) case: "Case" = Relationship(back_populates="data_store") + + +class CaseReportTemplateDataStore(SQLModel, table=True): + __tablename__ = "incident_management_case_report_template_datastore" + id: Optional[int] = Field(default=None, primary_key=True) + + report_template_name: str = Field(max_length=255, nullable=False) + bucket_name: str = Field(max_length=255, nullable=False) # Name of the MinIO bucket + object_key: str = Field(max_length=1024, nullable=False) # Path/key of the file in MinIO + file_name: str = Field(max_length=255, nullable=False) # Original file name uploaded by the user + content_type: Optional[str] = Field(max_length=100, nullable=True) # MIME type of the file + file_size: Optional[int] = Field(nullable=True) # File size in bytes + upload_time: datetime = Field(default_factory=datetime.utcnow) # Time of upload + file_hash: str = Field(max_length=128, nullable=False) # Hash of the file (e.g., SHA-256) From 866fe8892b0e3d6291ad00f4057c906954a9fcac Mon Sep 17 00:00:00 2001 From: Taylor Date: Thu, 3 Oct 2024 10:22:30 -0500 Subject: [PATCH 06/42] `chore: Add copilot-case-report-templates bucket creation during initialization` --- backend/app/data_store/data_store_setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/app/data_store/data_store_setup.py b/backend/app/data_store/data_store_setup.py index 4736b6ca..4a6e62f2 100644 --- a/backend/app/data_store/data_store_setup.py +++ b/backend/app/data_store/data_store_setup.py @@ -14,3 +14,4 @@ async def create_bucket_if_not_exists(bucket_name: str) -> None: async def create_buckets() -> None: await create_bucket_if_not_exists("copilot-cases") + await create_bucket_if_not_exists("copilot-case-report-templates") From 4302a75008b830482c99067389dd5362ca417d4f Mon Sep 17 00:00:00 2001 From: Taylor Date: Thu, 3 Oct 2024 10:24:19 -0500 Subject: [PATCH 07/42] `refactor: Update route for generating incident report CSV` --- backend/app/incidents/routes/incident_report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/app/incidents/routes/incident_report.py b/backend/app/incidents/routes/incident_report.py index b1acf192..6de93856 100644 --- a/backend/app/incidents/routes/incident_report.py +++ b/backend/app/incidents/routes/incident_report.py @@ -113,7 +113,7 @@ def generate_csv_content(rows: List[Dict[str, Any]]) -> StringIO: # Route Handler @incidents_report_router.post( - "/generate-report", + "/generate-report-csv", description="Generate a report for all cases.", ) async def get_cases_export_all_route( From bf3b732630c7e9bc31acc95e2dee10097f550ef4 Mon Sep 17 00:00:00 2001 From: Davide Di Modica Date: Thu, 3 Oct 2024 17:30:31 +0200 Subject: [PATCH 08/42] refactor: Update route for generating incident case report CSV --- frontend/src/api/endpoints/incidentManagement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/api/endpoints/incidentManagement.ts b/frontend/src/api/endpoints/incidentManagement.ts index bf32022b..eadcea2e 100644 --- a/frontend/src/api/endpoints/incidentManagement.ts +++ b/frontend/src/api/endpoints/incidentManagement.ts @@ -286,7 +286,7 @@ export default { return HttpClient.delete(`/incidents/db_operations/case/${caseId}`) }, exportCases(customerCode?: string) { - let url = `/incidents/report/generate-report` + let url = `/incidents/report/generate-report-csv` if (customerCode) { url = `/incidents/report/generate-report-csv/${customerCode}` From 24a3e8c812fc6fe3f5e8ce9828fdafd907b017ec Mon Sep 17 00:00:00 2001 From: Taylor Date: Thu, 3 Oct 2024 10:47:51 -0500 Subject: [PATCH 09/42] upload case report template to datastore and db --- .../app/data_store/data_store_operations.py | 25 ++++++++++- backend/app/data_store/data_store_schema.py | 10 +++++ backend/app/incidents/routes/db_operations.py | 20 +++++++-- backend/app/incidents/schema/db_operations.py | 9 +++- .../app/incidents/services/db_operations.py | 45 +++++++++++++++++-- 5 files changed, 101 insertions(+), 8 deletions(-) diff --git a/backend/app/data_store/data_store_operations.py b/backend/app/data_store/data_store_operations.py index 1a3d4164..90946289 100644 --- a/backend/app/data_store/data_store_operations.py +++ b/backend/app/data_store/data_store_operations.py @@ -6,7 +6,7 @@ from fastapi import UploadFile from loguru import logger -from app.data_store.data_store_schema import CaseDataStoreCreation +from app.data_store.data_store_schema import CaseDataStoreCreation, CaseReportTemplateDataStoreCreation from app.data_store.data_store_session import create_session @@ -42,6 +42,29 @@ async def upload_case_data_store(data: CaseDataStoreCreation, file: UploadFile) # Optionally, remove the temporary file after upload os.remove(temp_file_path) +async def upload_case_report_template_data_store(data: CaseReportTemplateDataStoreCreation, file: UploadFile) -> None: + client = await create_session() + logger.info(f"Uploading file {file.filename} to bucket {data.bucket_name}") + + # Define the temporary file path + temp_file_path = os.path.join(os.getcwd(), file.filename) + + # Save the file to the temporary location + async with aiofiles.open(temp_file_path, "wb") as out_file: + content = await file.read() + await out_file.write(content) + + # Upload the file to Minio + await client.fput_object( + bucket_name=data.bucket_name, + object_name=f"{file.filename}", + file_path=temp_file_path, + content_type=data.content_type, + ) + + # Optionally, remove the temporary file after upload + os.remove(temp_file_path) + async def download_case_data_store(bucket_name: str, object_name: str) -> bytes: client = await create_session() diff --git a/backend/app/data_store/data_store_schema.py b/backend/app/data_store/data_store_schema.py index fba82f09..e7b7d04b 100644 --- a/backend/app/data_store/data_store_schema.py +++ b/backend/app/data_store/data_store_schema.py @@ -14,3 +14,13 @@ class CaseDataStoreCreation(BaseModel): file_size: Optional[int] = None upload_time: datetime = Field(default_factory=datetime.utcnow) file_hash: str = Field(max_length=128) + + +class CaseReportTemplateDataStoreCreation(BaseModel): + report_template_name: str = Field(max_length=255) + bucket_name: str = Field(max_length=255) + object_key: str = Field(max_length=1024) + file_name: str = Field(max_length=255) + content_type: Optional[str] = Field(max_length=100, default=None) + upload_time: datetime = Field(default_factory=datetime.utcnow) + file_hash: str = Field(max_length=128) diff --git a/backend/app/incidents/routes/db_operations.py b/backend/app/incidents/routes/db_operations.py index 60f72fa6..728f3960 100644 --- a/backend/app/incidents/routes/db_operations.py +++ b/backend/app/incidents/routes/db_operations.py @@ -62,8 +62,8 @@ from app.incidents.schema.db_operations import SocfortressRecommendsWazuhResponse from app.incidents.schema.db_operations import SocfortressRecommendsWazuhTimeFieldName from app.incidents.schema.db_operations import UpdateAlertStatus -from app.incidents.schema.db_operations import UpdateCaseStatus -from app.incidents.services.db_operations import add_alert_title_name +from app.incidents.schema.db_operations import UpdateCaseStatus, CaseReportTemplateDataStoreResponse +from app.incidents.services.db_operations import add_alert_title_name, report_template_exists from app.incidents.services.db_operations import add_asset_name from app.incidents.services.db_operations import add_field_name from app.incidents.services.db_operations import add_timefield_name @@ -72,7 +72,7 @@ from app.incidents.services.db_operations import alert_total_by_assest_name from app.incidents.services.db_operations import alerts_closed from app.incidents.services.db_operations import alerts_closed_by_alert_title -from app.incidents.services.db_operations import alerts_closed_by_asset_name +from app.incidents.services.db_operations import alerts_closed_by_asset_name, upload_report_template from app.incidents.services.db_operations import alerts_closed_by_assigned_to from app.incidents.services.db_operations import alerts_closed_by_customer_code from app.incidents.services.db_operations import alerts_closed_by_source @@ -807,3 +807,17 @@ async def delete_case_data_store_file_endpoint(case_id: int, file_name: str, db: @incidents_db_operations_router.get("/case/{case_id}", response_model=CaseOutResponse) async def get_case_by_id_endpoint(case_id: int, db: AsyncSession = Depends(get_db)): return CaseOutResponse(cases=[await get_case_by_id(case_id, db)], success=True, message="Case retrieved successfully") + + +@incidents_db_operations_router.post("/case-report-template/upload", response_model=CaseReportTemplateDataStoreResponse) +async def upload_case_report_template_endpoint( + file: UploadFile = File(...), + db: AsyncSession = Depends(get_db), +): + if await report_template_exists(file.filename, db): + raise HTTPException(status_code=400, detail="File name already exists for this template") + return CaseReportTemplateDataStoreResponse( + case_report_template_data_store=await upload_report_template(file, db), + success=True, + message="File uploaded successfully", + ) diff --git a/backend/app/incidents/schema/db_operations.py b/backend/app/incidents/schema/db_operations.py index 5a9e3240..0bf62cda 100644 --- a/backend/app/incidents/schema/db_operations.py +++ b/backend/app/incidents/schema/db_operations.py @@ -10,7 +10,7 @@ from app.incidents.models import AlertContext from app.incidents.models import AlertTag from app.incidents.models import Asset -from app.incidents.models import Case +from app.incidents.models import Case, CaseReportTemplateDataStore from app.incidents.models import CaseAlertLink from app.incidents.models import CaseDataStore from app.incidents.models import Comment @@ -348,3 +348,10 @@ class ListCaseDataStoreResponse(BaseModel): case_data_store: List[CaseDataStore] success: bool message: str + + +class CaseReportTemplateDataStoreResponse(BaseModel): + case_report_template_data_store: CaseReportTemplateDataStore + success: bool + message: str + diff --git a/backend/app/incidents/services/db_operations.py b/backend/app/incidents/services/db_operations.py index 17d0291e..825c1453 100644 --- a/backend/app/incidents/services/db_operations.py +++ b/backend/app/incidents/services/db_operations.py @@ -18,8 +18,8 @@ from app.data_store.data_store_operations import delete_file from app.data_store.data_store_operations import download_case_data_store -from app.data_store.data_store_operations import upload_case_data_store -from app.data_store.data_store_schema import CaseDataStoreCreation +from app.data_store.data_store_operations import upload_case_data_store, upload_case_report_template_data_store +from app.data_store.data_store_schema import CaseDataStoreCreation, CaseReportTemplateDataStoreCreation from app.incidents.models import Alert from app.incidents.models import AlertContext from app.incidents.models import AlertTag @@ -31,7 +31,7 @@ from app.incidents.models import CaseAlertLink from app.incidents.models import CaseDataStore from app.incidents.models import Comment -from app.incidents.models import CustomerCodeFieldName +from app.incidents.models import CustomerCodeFieldName, CaseReportTemplateDataStore from app.incidents.models import FieldName from app.incidents.models import Notification from app.incidents.models import TimestampFieldName @@ -1732,6 +1732,11 @@ async def file_exists(case_id: int, file_name: str, db: AsyncSession) -> bool: result = await db.execute(query) return result.scalars().first() is not None +async def report_template_exists(file_name: str, db: AsyncSession) -> bool: + query = select(CaseReportTemplateDataStore).where(CaseReportTemplateDataStore.report_template_name == file_name) + result = await db.execute(query) + return result.scalars().first() is not None + async def sha256_hash_file(file: UploadFile) -> str: await file.seek(0) @@ -1760,6 +1765,20 @@ async def add_file_to_db(case_id: int, file: UploadFile, file_size: int, file_ha await db.commit() return db_file +async def add_report_template_to_db(file: UploadFile, file_size: int, file_hash: str, db: AsyncSession) -> None: + db_file = CaseReportTemplateDataStore( + report_template_name=file.filename, + bucket_name="copilot-case-report-templates", + object_key=file.filename, + content_type=file.content_type, + file_name=file.filename, + file_size=file_size, + file_hash=file_hash, + ) + db.add(db_file) + await db.commit() + return db_file + async def upload_file_to_case(case_id: int, file: UploadFile, db: AsyncSession) -> CaseDataStore: file_size = await get_file_size(file) @@ -1781,6 +1800,26 @@ async def upload_file_to_case(case_id: int, file: UploadFile, db: AsyncSession) # Add the file to the database return await add_file_to_db(case_id, file, file_size, file_hash, db) +async def upload_report_template(file: UploadFile, db: AsyncSession) -> CaseReportTemplateDataStore: + file_size = await get_file_size(file) + file_hash = await sha256_hash_file(file) + await file.seek(0) + # Upload the file to Minio + await upload_case_report_template_data_store( + data=CaseReportTemplateDataStoreCreation( + report_template_name=file.filename, + bucket_name="copilot-case-report-templates", + object_key=file.filename, + file_name=file.filename, + content_type=file.content_type, + file_hash=file_hash, + ), + file=file, + ) + + # Add the file to the database + return await add_report_template_to_db(file, file_size, file_hash, db) + async def get_file_by_case_id_and_name(case_id: int, file_name: str, db: AsyncSession) -> CaseDataStore: logger.info(f"Getting file {file_name} from case {case_id}") From 86ed39c6d4690f9d57f0ee5f1c207a8122153570 Mon Sep 17 00:00:00 2001 From: Taylor Date: Thu, 3 Oct 2024 10:55:11 -0500 Subject: [PATCH 10/42] delete case report template functions and route --- backend/app/incidents/routes/db_operations.py | 8 +++++++- .../app/incidents/services/db_operations.py | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/backend/app/incidents/routes/db_operations.py b/backend/app/incidents/routes/db_operations.py index 728f3960..813e3b73 100644 --- a/backend/app/incidents/routes/db_operations.py +++ b/backend/app/incidents/routes/db_operations.py @@ -63,7 +63,7 @@ from app.incidents.schema.db_operations import SocfortressRecommendsWazuhTimeFieldName from app.incidents.schema.db_operations import UpdateAlertStatus from app.incidents.schema.db_operations import UpdateCaseStatus, CaseReportTemplateDataStoreResponse -from app.incidents.services.db_operations import add_alert_title_name, report_template_exists +from app.incidents.services.db_operations import add_alert_title_name, report_template_exists, delete_report_template from app.incidents.services.db_operations import add_asset_name from app.incidents.services.db_operations import add_field_name from app.incidents.services.db_operations import add_timefield_name @@ -821,3 +821,9 @@ async def upload_case_report_template_endpoint( success=True, message="File uploaded successfully", ) + + +@incidents_db_operations_router.delete("/case-report-template/{file_name}") +async def delete_case_report_template_endpoint(file_name: str, db: AsyncSession = Depends(get_db)): + await delete_report_template(file_name, db) + return {"message": "File deleted successfully", "success": True} diff --git a/backend/app/incidents/services/db_operations.py b/backend/app/incidents/services/db_operations.py index 825c1453..7a87acdb 100644 --- a/backend/app/incidents/services/db_operations.py +++ b/backend/app/incidents/services/db_operations.py @@ -1827,11 +1827,21 @@ async def get_file_by_case_id_and_name(case_id: int, file_name: str, db: AsyncSe result = await db.execute(query) return result.scalars().first() +async def get_report_template_by_name(file_name: str, db: AsyncSession) -> CaseReportTemplateDataStore: + logger.info(f"Getting file {file_name}") + query = select(CaseReportTemplateDataStore).where(CaseReportTemplateDataStore.report_template_name == file_name) + result = await db.execute(query) + return result.scalars().first() + async def remove_file_from_db(file_id: int, db: AsyncSession) -> None: await db.execute(delete(CaseDataStore).where(CaseDataStore.id == file_id)) await db.commit() +async def remove_report_template_from_db(file_id: int, db: AsyncSession) -> None: + await db.execute(delete(CaseReportTemplateDataStore).where(CaseReportTemplateDataStore.id == file_id)) + await db.commit() + async def delete_file_from_case(case_id: int, file_name: str, db: AsyncSession) -> None: file = await get_file_by_case_id_and_name(case_id, file_name, db) @@ -1849,3 +1859,11 @@ async def download_file_from_case(case_id: int, file_name: str, db: AsyncSession file_content = await download_case_data_store(file.bucket_name, file.object_key) return file_content, file.content_type + +async def delete_report_template(file_name: str, db: AsyncSession) -> None: + file = await get_report_template_by_name(file_name, db) + if not file: + raise HTTPException(status_code=404, detail="File not found") + + await delete_file(file.bucket_name, file.object_key) + await remove_report_template_from_db(file.id, db) From de8002f44838e68412686f3c1da19e0a437fe1c9 Mon Sep 17 00:00:00 2001 From: Taylor Date: Thu, 3 Oct 2024 11:02:01 -0500 Subject: [PATCH 11/42] download report template function and route --- backend/app/data_store/data_store_operations.py | 2 +- backend/app/incidents/routes/db_operations.py | 10 +++++++++- backend/app/incidents/services/db_operations.py | 12 ++++++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/backend/app/data_store/data_store_operations.py b/backend/app/data_store/data_store_operations.py index 90946289..a9d2190b 100644 --- a/backend/app/data_store/data_store_operations.py +++ b/backend/app/data_store/data_store_operations.py @@ -66,7 +66,7 @@ async def upload_case_report_template_data_store(data: CaseReportTemplateDataSto os.remove(temp_file_path) -async def download_case_data_store(bucket_name: str, object_name: str) -> bytes: +async def download_data_store(bucket_name: str, object_name: str) -> bytes: client = await create_session() logger.info(f"Downloading file {object_name} from bucket {bucket_name}") try: diff --git a/backend/app/incidents/routes/db_operations.py b/backend/app/incidents/routes/db_operations.py index 813e3b73..1820effd 100644 --- a/backend/app/incidents/routes/db_operations.py +++ b/backend/app/incidents/routes/db_operations.py @@ -67,7 +67,7 @@ from app.incidents.services.db_operations import add_asset_name from app.incidents.services.db_operations import add_field_name from app.incidents.services.db_operations import add_timefield_name -from app.incidents.services.db_operations import alert_total +from app.incidents.services.db_operations import alert_total, download_report_template from app.incidents.services.db_operations import alert_total_by_alert_title from app.incidents.services.db_operations import alert_total_by_assest_name from app.incidents.services.db_operations import alerts_closed @@ -808,6 +808,14 @@ async def delete_case_data_store_file_endpoint(case_id: int, file_name: str, db: async def get_case_by_id_endpoint(case_id: int, db: AsyncSession = Depends(get_db)): return CaseOutResponse(cases=[await get_case_by_id(case_id, db)], success=True, message="Case retrieved successfully") +@incidents_db_operations_router.get("/case-report-template/download/{file_name}") +async def download_case_report_template_endpoint(file_name: str, db: AsyncSession = Depends(get_db)) -> StreamingResponse: + file_bytes, file_content_type = await download_report_template(file_name, db) + logger.info(f"Streaming file {file_name}") + output = io.BytesIO(file_bytes) + output.seek(0) + + return StreamingResponse(output, media_type=file_content_type, headers={"Content-Disposition": f"attachment; filename={file_name}"}) @incidents_db_operations_router.post("/case-report-template/upload", response_model=CaseReportTemplateDataStoreResponse) async def upload_case_report_template_endpoint( diff --git a/backend/app/incidents/services/db_operations.py b/backend/app/incidents/services/db_operations.py index 7a87acdb..a640065a 100644 --- a/backend/app/incidents/services/db_operations.py +++ b/backend/app/incidents/services/db_operations.py @@ -17,7 +17,7 @@ from sqlalchemy.orm import selectinload from app.data_store.data_store_operations import delete_file -from app.data_store.data_store_operations import download_case_data_store +from app.data_store.data_store_operations import download_data_store from app.data_store.data_store_operations import upload_case_data_store, upload_case_report_template_data_store from app.data_store.data_store_schema import CaseDataStoreCreation, CaseReportTemplateDataStoreCreation from app.incidents.models import Alert @@ -1857,7 +1857,7 @@ async def download_file_from_case(case_id: int, file_name: str, db: AsyncSession if not file: raise HTTPException(status_code=404, detail="File not found") - file_content = await download_case_data_store(file.bucket_name, file.object_key) + file_content = await download_data_store(file.bucket_name, file.object_key) return file_content, file.content_type async def delete_report_template(file_name: str, db: AsyncSession) -> None: @@ -1867,3 +1867,11 @@ async def delete_report_template(file_name: str, db: AsyncSession) -> None: await delete_file(file.bucket_name, file.object_key) await remove_report_template_from_db(file.id, db) + +async def download_report_template(file_name: str, db: AsyncSession) -> Tuple[bytes, str]: + file = await get_report_template_by_name(file_name, db) + if not file: + raise HTTPException(status_code=404, detail="File not found") + + file_content = await download_data_store(file.bucket_name, file.object_key) + return file_content, file.content_type From ad7e8209f0ecf051b32221475452e74c38db9db1 Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 4 Oct 2024 11:20:28 -0500 Subject: [PATCH 12/42] testing downloading case and applying jinja template --- .../app/incidents/routes/incident_report.py | 36 ++++++++++++- backend/app/incidents/services/reports.py | 50 +++++++++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 backend/app/incidents/services/reports.py diff --git a/backend/app/incidents/routes/incident_report.py b/backend/app/incidents/routes/incident_report.py index 6de93856..921875ae 100644 --- a/backend/app/incidents/routes/incident_report.py +++ b/backend/app/incidents/routes/incident_report.py @@ -3,10 +3,13 @@ from io import StringIO from typing import Any from typing import Dict +from docxtpl import DocxTemplate +from fastapi.responses import FileResponse from typing import List - -from fastapi import APIRouter +import os +from fastapi import APIRouter, HTTPException from fastapi import Depends +from tempfile import NamedTemporaryFile from fastapi.responses import StreamingResponse from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload @@ -15,6 +18,7 @@ from app.customers.routes.customers import get_customer from app.db.db_session import get_db from app.incidents.models import Alert +from app.incidents.services.reports import download_template, create_case_context, save_template_to_tempfile, render_document_with_context, create_file_response, cleanup_temp_files from app.incidents.models import AlertToTag from app.incidents.models import Case from app.incidents.models import CaseAlertLink @@ -144,3 +148,31 @@ async def get_cases_export_customer_route( response = StreamingResponse(csv_stream, media_type="text/csv") response.headers["Content-Disposition"] = f"attachment; filename={filename}" return response + + +@incidents_report_router.post( + "/generate-report-docx", + description="Generate a docx report for a case.", +) +async def get_cases_export_docx_route( + template_name: str, + session: AsyncSession = Depends(get_db), +) -> FileResponse: + cases = await fetch_cases_with_related_data(session) + if not cases: + raise HTTPException(status_code=404, detail="No cases found") + + first_case = cases[0] + context = create_case_context(first_case) + + template_file_content = await download_template(template_name) + tmp_template_name = save_template_to_tempfile(template_file_content) + + rendered_file_name = render_document_with_context(tmp_template_name, context) + + response = create_file_response(rendered_file_name) + + # Clean up temporary files + cleanup_temp_files([tmp_template_name]) + + return response diff --git a/backend/app/incidents/services/reports.py b/backend/app/incidents/services/reports.py new file mode 100644 index 00000000..8dd77678 --- /dev/null +++ b/backend/app/incidents/services/reports.py @@ -0,0 +1,50 @@ +from typing import Dict +from fastapi.responses import FileResponse +from tempfile import NamedTemporaryFile +import os +from docxtpl import DocxTemplate +from app.data_store.data_store_operations import download_data_store + +async def download_template(template_name: str) -> bytes: + """Retrieve the template file content from the data store.""" + return await download_data_store(bucket_name="copilot-case-report-templates", object_name=template_name) + +def create_case_context(case) -> Dict[str, Dict[str, str]]: + """Prepare the context for the Jinja template.""" + return { + "case": { + "name": case.case_name, + "description": case.case_description, + "assigned_to": case.assigned_to, + "case_creation_time": case.case_creation_time, + "id": case.id, + } + } + +def save_template_to_tempfile(template_file_content: bytes) -> str: + """Save the template content to a temporary file.""" + with NamedTemporaryFile(delete=False, suffix=".docx") as tmp_template: + tmp_template.write(template_file_content) + return tmp_template.name + +def render_document_with_context(template_path: str, context: Dict[str, Dict[str, str]]) -> str: + """Load and render the document template with the given context.""" + doc = DocxTemplate(template_path) + doc.render(context) + with NamedTemporaryFile(delete=False, suffix=".docx") as tmp: + doc.save(tmp.name) + return tmp.name + +def create_file_response(file_path: str) -> FileResponse: + """Create a FileResponse object for the rendered document.""" + return FileResponse( + file_path, + filename="case_report.docx", + media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document", + ) + +def cleanup_temp_files(file_paths: list): + """Clean up the temporary files.""" + for file_path in file_paths: + if os.path.exists(file_path): + os.remove(file_path) From eac575b715e6f4b1b6c10ee894151f96bad7e3c7 Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 4 Oct 2024 11:54:12 -0500 Subject: [PATCH 13/42] loading alert with context --- .../app/incidents/routes/incident_report.py | 32 ++++++++-- backend/app/incidents/services/reports.py | 59 +++++++++++++++++++ 2 files changed, 86 insertions(+), 5 deletions(-) diff --git a/backend/app/incidents/routes/incident_report.py b/backend/app/incidents/routes/incident_report.py index 921875ae..b15e5b13 100644 --- a/backend/app/incidents/routes/incident_report.py +++ b/backend/app/incidents/routes/incident_report.py @@ -17,11 +17,12 @@ from app.customers.routes.customers import get_customer from app.db.db_session import get_db -from app.incidents.models import Alert +from app.incidents.models import Alert, Asset from app.incidents.services.reports import download_template, create_case_context, save_template_to_tempfile, render_document_with_context, create_file_response, cleanup_temp_files from app.incidents.models import AlertToTag from app.incidents.models import Case from app.incidents.models import CaseAlertLink +from loguru import logger incidents_report_router = APIRouter() @@ -75,6 +76,24 @@ async def fetch_cases_by_customer(session: AsyncSession, customer_code: str) -> ) return result.scalars().all() +async def fetch_case_by_id(session: AsyncSession, case_id: int) -> Case: + """Fetch a case by its ID.""" + result = await session.execute( + select(Case) + .where(Case.id == case_id) + .options( + selectinload(Case.alerts) + .selectinload(CaseAlertLink.alert) + .options( + selectinload(Alert.assets).selectinload(Asset.alert_context), # Load alert_context + selectinload(Alert.tags).selectinload(AlertToTag.tag), + selectinload(Alert.comments) + ), + ), + ) + return result.scalars().first() + + def serialize_case_alert_to_row(case: Case, alert: Alert) -> Dict[str, Any]: """Serialize a case and its alert into a CSV row.""" @@ -156,14 +175,17 @@ async def get_cases_export_customer_route( ) async def get_cases_export_docx_route( template_name: str, + case_id: int, session: AsyncSession = Depends(get_db), ) -> FileResponse: - cases = await fetch_cases_with_related_data(session) - if not cases: + case = await fetch_case_by_id(session, case_id) + if not case: raise HTTPException(status_code=404, detail="No cases found") - first_case = cases[0] - context = create_case_context(first_case) + logger.info(f"Case: {case}") + + context = create_case_context(case) + logger.info(f"Context: {context}") template_file_content = await download_template(template_name) tmp_template_name = save_template_to_tempfile(template_file_content) diff --git a/backend/app/incidents/services/reports.py b/backend/app/incidents/services/reports.py index 8dd77678..e6e57a3f 100644 --- a/backend/app/incidents/services/reports.py +++ b/backend/app/incidents/services/reports.py @@ -4,11 +4,40 @@ import os from docxtpl import DocxTemplate from app.data_store.data_store_operations import download_data_store +from loguru import logger async def download_template(template_name: str) -> bytes: """Retrieve the template file content from the data store.""" return await download_data_store(bucket_name="copilot-case-report-templates", object_name=template_name) +# def create_case_context(case) -> Dict[str, Dict[str, str]]: +# """Prepare the context for the Jinja template.""" +# return { +# "case": { +# "name": case.case_name, +# "description": case.case_description, +# "assigned_to": case.assigned_to, +# "case_creation_time": case.case_creation_time, +# "id": case.id, +# "alerts": [ +# { +# "alert_name": alert.alert.alert_name, +# "alert_description": alert.alert.alert_description, +# "status": alert.alert.status, +# "tags": [tag.tag.tag for tag in alert.alert.tags], +# "assets": [ +# { +# "asset_name": asset.asset_name, +# "agent_id": asset.agent_id, +# } +# for asset in alert.alert.assets +# ] +# } +# for alert in case.alerts +# ] +# } +# } + def create_case_context(case) -> Dict[str, Dict[str, str]]: """Prepare the context for the Jinja template.""" return { @@ -18,9 +47,39 @@ def create_case_context(case) -> Dict[str, Dict[str, str]]: "assigned_to": case.assigned_to, "case_creation_time": case.case_creation_time, "id": case.id, + "alerts": [ + { + "alert_name": alert.alert.alert_name, + "alert_description": alert.alert.alert_description, + "status": alert.alert.status, + "tags": [tag.tag.tag for tag in alert.alert.tags], + "assets": [ + { + "asset_name": asset.asset_name, + "agent_id": asset.agent_id, + } + for asset in alert.alert.assets + ], + "comments": [ + { + "comment": comment.comment, + "user_name": comment.user_name, + "created_at": comment.created_at, + } + for comment in alert.alert.comments + ], + "context": { + "source": alert.alert.assets[0].alert_context.source if alert.alert.assets and alert.alert.assets[0].alert_context else None, + "context": alert.alert.assets[0].alert_context.context if alert.alert.assets and alert.alert.assets[0].alert_context else None, + } if alert.alert.assets else None + } + for alert in case.alerts + ] } } + + def save_template_to_tempfile(template_file_content: bytes) -> str: """Save the template content to a temporary file.""" with NamedTemporaryFile(delete=False, suffix=".docx") as tmp_template: From 373d99adc9a23f9536109922e34bd43cf961ffcc Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 4 Oct 2024 12:07:49 -0500 Subject: [PATCH 14/42] `refactor: Remove commented out code for creating case context` --- .../app/incidents/routes/incident_report.py | 3 -- backend/app/incidents/services/reports.py | 28 ------------------- 2 files changed, 31 deletions(-) diff --git a/backend/app/incidents/routes/incident_report.py b/backend/app/incidents/routes/incident_report.py index b15e5b13..893fd268 100644 --- a/backend/app/incidents/routes/incident_report.py +++ b/backend/app/incidents/routes/incident_report.py @@ -182,10 +182,7 @@ async def get_cases_export_docx_route( if not case: raise HTTPException(status_code=404, detail="No cases found") - logger.info(f"Case: {case}") - context = create_case_context(case) - logger.info(f"Context: {context}") template_file_content = await download_template(template_name) tmp_template_name = save_template_to_tempfile(template_file_content) diff --git a/backend/app/incidents/services/reports.py b/backend/app/incidents/services/reports.py index e6e57a3f..0a5fefbf 100644 --- a/backend/app/incidents/services/reports.py +++ b/backend/app/incidents/services/reports.py @@ -10,34 +10,6 @@ async def download_template(template_name: str) -> bytes: """Retrieve the template file content from the data store.""" return await download_data_store(bucket_name="copilot-case-report-templates", object_name=template_name) -# def create_case_context(case) -> Dict[str, Dict[str, str]]: -# """Prepare the context for the Jinja template.""" -# return { -# "case": { -# "name": case.case_name, -# "description": case.case_description, -# "assigned_to": case.assigned_to, -# "case_creation_time": case.case_creation_time, -# "id": case.id, -# "alerts": [ -# { -# "alert_name": alert.alert.alert_name, -# "alert_description": alert.alert.alert_description, -# "status": alert.alert.status, -# "tags": [tag.tag.tag for tag in alert.alert.tags], -# "assets": [ -# { -# "asset_name": asset.asset_name, -# "agent_id": asset.agent_id, -# } -# for asset in alert.alert.assets -# ] -# } -# for alert in case.alerts -# ] -# } -# } - def create_case_context(case) -> Dict[str, Dict[str, str]]: """Prepare the context for the Jinja template.""" return { From afbb02c2ca9717a49a5a3ee68d2d6ed451cf3070 Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 4 Oct 2024 13:17:53 -0500 Subject: [PATCH 15/42] build for wazuh group template creation fix --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7003bdea..0ed70d86 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Docker on: push: - branches: [main] + branches: [incident-reports-docx] jobs: build-backend: From 741a172378e97527a002617976428fdf915c762b Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 4 Oct 2024 13:18:19 -0500 Subject: [PATCH 16/42] `chore: Update branch name in Docker workflow` --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0ed70d86..7003bdea 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Docker on: push: - branches: [incident-reports-docx] + branches: [main] jobs: build-backend: From 0a4f7ae868fea3f71c81bfd442cf51555692865a Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 4 Oct 2024 13:36:02 -0500 Subject: [PATCH 17/42] add docxtpl to requirements --- .github/workflows/docker.yml | 2 +- backend/requirements.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7003bdea..0ed70d86 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Docker on: push: - branches: [main] + branches: [incident-reports-docx] jobs: build-backend: diff --git a/backend/requirements.txt b/backend/requirements.txt index 4d962086..8d33d204 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -109,6 +109,7 @@ prompt-toolkit==3.0.39 protobuf==4.24.4 psycopg2-binary==2.9.9 pyasn1==0.5.0 +docxtpl==0.18.0 pycountry==22.3.5 pycparser==2.21 # pydantic==1.10.13 From 1f34c9957e3f5cd198a634ea460ac55467df6c93 Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 4 Oct 2024 13:36:24 -0500 Subject: [PATCH 18/42] `chore: Update branch name in Docker workflow` --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0ed70d86..7003bdea 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Docker on: push: - branches: [incident-reports-docx] + branches: [main] jobs: build-backend: From fcb9e28c15e2f3eaf68739362d50a6a58967a08a Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 4 Oct 2024 13:41:21 -0500 Subject: [PATCH 19/42] bump lxml down --- .github/workflows/docker.yml | 2 +- backend/requirements.txt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7003bdea..0ed70d86 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Docker on: push: - branches: [main] + branches: [incident-reports-docx] jobs: build-backend: diff --git a/backend/requirements.txt b/backend/requirements.txt index 8d33d204..6f159a9f 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -72,7 +72,8 @@ kombu==5.3.2 libmagic==1.0 licensing==0.43 loguru==0.7.2 -lxml==4.9.3 +#lxml==4.9.3 Bump down for python-docx +lxml==4.9.2 maec==4.1.0.17 Markdown==3.4.4 markdown-it-py==3.0.0 From e05f0af64400ca60e049be93aec9f6406ba7af44 Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 4 Oct 2024 13:41:44 -0500 Subject: [PATCH 20/42] `chore: Update branch name in Docker workflow` --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0ed70d86..7003bdea 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Docker on: push: - branches: [incident-reports-docx] + branches: [main] jobs: build-backend: From 539d2c3b837675b1742dc6f67f2cb46334b2df9f Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 4 Oct 2024 13:46:46 -0500 Subject: [PATCH 21/42] comment docx out for now --- .github/workflows/docker.yml | 2 +- .../app/incidents/routes/incident_report.py | 41 +++-- backend/app/incidents/services/reports.py | 146 +++++++++--------- backend/requirements.txt | 2 +- 4 files changed, 95 insertions(+), 96 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7003bdea..0ed70d86 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Docker on: push: - branches: [main] + branches: [incident-reports-docx] jobs: build-backend: diff --git a/backend/app/incidents/routes/incident_report.py b/backend/app/incidents/routes/incident_report.py index 893fd268..a4a382f9 100644 --- a/backend/app/incidents/routes/incident_report.py +++ b/backend/app/incidents/routes/incident_report.py @@ -3,7 +3,6 @@ from io import StringIO from typing import Any from typing import Dict -from docxtpl import DocxTemplate from fastapi.responses import FileResponse from typing import List import os @@ -169,29 +168,29 @@ async def get_cases_export_customer_route( return response -@incidents_report_router.post( - "/generate-report-docx", - description="Generate a docx report for a case.", -) -async def get_cases_export_docx_route( - template_name: str, - case_id: int, - session: AsyncSession = Depends(get_db), -) -> FileResponse: - case = await fetch_case_by_id(session, case_id) - if not case: - raise HTTPException(status_code=404, detail="No cases found") +# @incidents_report_router.post( +# "/generate-report-docx", +# description="Generate a docx report for a case.", +# ) +# async def get_cases_export_docx_route( +# template_name: str, +# case_id: int, +# session: AsyncSession = Depends(get_db), +# ) -> FileResponse: +# case = await fetch_case_by_id(session, case_id) +# if not case: +# raise HTTPException(status_code=404, detail="No cases found") - context = create_case_context(case) +# context = create_case_context(case) - template_file_content = await download_template(template_name) - tmp_template_name = save_template_to_tempfile(template_file_content) +# template_file_content = await download_template(template_name) +# tmp_template_name = save_template_to_tempfile(template_file_content) - rendered_file_name = render_document_with_context(tmp_template_name, context) +# rendered_file_name = render_document_with_context(tmp_template_name, context) - response = create_file_response(rendered_file_name) +# response = create_file_response(rendered_file_name) - # Clean up temporary files - cleanup_temp_files([tmp_template_name]) +# # Clean up temporary files +# cleanup_temp_files([tmp_template_name]) - return response +# return response diff --git a/backend/app/incidents/services/reports.py b/backend/app/incidents/services/reports.py index 0a5fefbf..9f51da35 100644 --- a/backend/app/incidents/services/reports.py +++ b/backend/app/incidents/services/reports.py @@ -1,81 +1,81 @@ -from typing import Dict -from fastapi.responses import FileResponse -from tempfile import NamedTemporaryFile -import os -from docxtpl import DocxTemplate -from app.data_store.data_store_operations import download_data_store -from loguru import logger +# from typing import Dict +# from fastapi.responses import FileResponse +# from tempfile import NamedTemporaryFile +# import os +# from docxtpl import DocxTemplate +# from app.data_store.data_store_operations import download_data_store +# from loguru import logger -async def download_template(template_name: str) -> bytes: - """Retrieve the template file content from the data store.""" - return await download_data_store(bucket_name="copilot-case-report-templates", object_name=template_name) +# async def download_template(template_name: str) -> bytes: +# """Retrieve the template file content from the data store.""" +# return await download_data_store(bucket_name="copilot-case-report-templates", object_name=template_name) -def create_case_context(case) -> Dict[str, Dict[str, str]]: - """Prepare the context for the Jinja template.""" - return { - "case": { - "name": case.case_name, - "description": case.case_description, - "assigned_to": case.assigned_to, - "case_creation_time": case.case_creation_time, - "id": case.id, - "alerts": [ - { - "alert_name": alert.alert.alert_name, - "alert_description": alert.alert.alert_description, - "status": alert.alert.status, - "tags": [tag.tag.tag for tag in alert.alert.tags], - "assets": [ - { - "asset_name": asset.asset_name, - "agent_id": asset.agent_id, - } - for asset in alert.alert.assets - ], - "comments": [ - { - "comment": comment.comment, - "user_name": comment.user_name, - "created_at": comment.created_at, - } - for comment in alert.alert.comments - ], - "context": { - "source": alert.alert.assets[0].alert_context.source if alert.alert.assets and alert.alert.assets[0].alert_context else None, - "context": alert.alert.assets[0].alert_context.context if alert.alert.assets and alert.alert.assets[0].alert_context else None, - } if alert.alert.assets else None - } - for alert in case.alerts - ] - } - } +# def create_case_context(case) -> Dict[str, Dict[str, str]]: +# """Prepare the context for the Jinja template.""" +# return { +# "case": { +# "name": case.case_name, +# "description": case.case_description, +# "assigned_to": case.assigned_to, +# "case_creation_time": case.case_creation_time, +# "id": case.id, +# "alerts": [ +# { +# "alert_name": alert.alert.alert_name, +# "alert_description": alert.alert.alert_description, +# "status": alert.alert.status, +# "tags": [tag.tag.tag for tag in alert.alert.tags], +# "assets": [ +# { +# "asset_name": asset.asset_name, +# "agent_id": asset.agent_id, +# } +# for asset in alert.alert.assets +# ], +# "comments": [ +# { +# "comment": comment.comment, +# "user_name": comment.user_name, +# "created_at": comment.created_at, +# } +# for comment in alert.alert.comments +# ], +# "context": { +# "source": alert.alert.assets[0].alert_context.source if alert.alert.assets and alert.alert.assets[0].alert_context else None, +# "context": alert.alert.assets[0].alert_context.context if alert.alert.assets and alert.alert.assets[0].alert_context else None, +# } if alert.alert.assets else None +# } +# for alert in case.alerts +# ] +# } +# } -def save_template_to_tempfile(template_file_content: bytes) -> str: - """Save the template content to a temporary file.""" - with NamedTemporaryFile(delete=False, suffix=".docx") as tmp_template: - tmp_template.write(template_file_content) - return tmp_template.name +# def save_template_to_tempfile(template_file_content: bytes) -> str: +# """Save the template content to a temporary file.""" +# with NamedTemporaryFile(delete=False, suffix=".docx") as tmp_template: +# tmp_template.write(template_file_content) +# return tmp_template.name -def render_document_with_context(template_path: str, context: Dict[str, Dict[str, str]]) -> str: - """Load and render the document template with the given context.""" - doc = DocxTemplate(template_path) - doc.render(context) - with NamedTemporaryFile(delete=False, suffix=".docx") as tmp: - doc.save(tmp.name) - return tmp.name +# def render_document_with_context(template_path: str, context: Dict[str, Dict[str, str]]) -> str: +# """Load and render the document template with the given context.""" +# doc = DocxTemplate(template_path) +# doc.render(context) +# with NamedTemporaryFile(delete=False, suffix=".docx") as tmp: +# doc.save(tmp.name) +# return tmp.name -def create_file_response(file_path: str) -> FileResponse: - """Create a FileResponse object for the rendered document.""" - return FileResponse( - file_path, - filename="case_report.docx", - media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document", - ) +# def create_file_response(file_path: str) -> FileResponse: +# """Create a FileResponse object for the rendered document.""" +# return FileResponse( +# file_path, +# filename="case_report.docx", +# media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document", +# ) -def cleanup_temp_files(file_paths: list): - """Clean up the temporary files.""" - for file_path in file_paths: - if os.path.exists(file_path): - os.remove(file_path) +# def cleanup_temp_files(file_paths: list): +# """Clean up the temporary files.""" +# for file_path in file_paths: +# if os.path.exists(file_path): +# os.remove(file_path) diff --git a/backend/requirements.txt b/backend/requirements.txt index 6f159a9f..946c1483 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -110,7 +110,7 @@ prompt-toolkit==3.0.39 protobuf==4.24.4 psycopg2-binary==2.9.9 pyasn1==0.5.0 -docxtpl==0.18.0 +#docxtpl==0.18.0 Comment out for now pycountry==22.3.5 pycparser==2.21 # pydantic==1.10.13 From 01674b244a180e393398305b91cd1cc471155700 Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 4 Oct 2024 13:47:04 -0500 Subject: [PATCH 22/42] `chore: Update branch name in Docker workflow` --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0ed70d86..7003bdea 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Docker on: push: - branches: [incident-reports-docx] + branches: [main] jobs: build-backend: From 90b242dcd0fb10f091fd09b60f58aa17c009fce4 Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 4 Oct 2024 14:22:11 -0500 Subject: [PATCH 23/42] `chore: Update branch name in Docker workflow` --- .github/workflows/docker.yml | 2 +- backend/app/incidents/routes/incident_report.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7003bdea..0ed70d86 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Docker on: push: - branches: [main] + branches: [incident-reports-docx] jobs: build-backend: diff --git a/backend/app/incidents/routes/incident_report.py b/backend/app/incidents/routes/incident_report.py index a4a382f9..4fc2c578 100644 --- a/backend/app/incidents/routes/incident_report.py +++ b/backend/app/incidents/routes/incident_report.py @@ -17,7 +17,7 @@ from app.customers.routes.customers import get_customer from app.db.db_session import get_db from app.incidents.models import Alert, Asset -from app.incidents.services.reports import download_template, create_case_context, save_template_to_tempfile, render_document_with_context, create_file_response, cleanup_temp_files +#from app.incidents.services.reports import download_template, create_case_context, save_template_to_tempfile, render_document_with_context, create_file_response, cleanup_temp_files from app.incidents.models import AlertToTag from app.incidents.models import Case from app.incidents.models import CaseAlertLink From d6804917e63c54ab62f2a2a619a9b2ef1f00a4b9 Mon Sep 17 00:00:00 2001 From: Taylor Date: Fri, 4 Oct 2024 14:22:39 -0500 Subject: [PATCH 24/42] `chore: Update branch name in Docker workflow` --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0ed70d86..7003bdea 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Docker on: push: - branches: [incident-reports-docx] + branches: [main] jobs: build-backend: From d7440d23f124a21021061fccc395198395451344 Mon Sep 17 00:00:00 2001 From: Taylor Date: Mon, 14 Oct 2024 08:38:51 -0500 Subject: [PATCH 25/42] reimplment docx --- .github/workflows/docker.yml | 6 +- .../app/incidents/routes/incident_report.py | 42 ++--- backend/app/incidents/services/reports.py | 146 +++++++++--------- backend/requirements.txt | 2 +- 4 files changed, 98 insertions(+), 98 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7003bdea..4dc403cb 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Docker on: push: - branches: [main] + branches: [incident-reports-docx] jobs: build-backend: @@ -27,7 +27,7 @@ jobs: with: context: ./backend push: true - tags: ghcr.io/socfortress/copilot-backend:latest + tags: ghcr.io/socfortress/copilot-backend:lab build-args: | COPILOT_API_KEY=${{ secrets.COPILOT_API_KEY }} @@ -60,7 +60,7 @@ jobs: with: context: ./frontend push: true - tags: ghcr.io/socfortress/copilot-frontend:latest + tags: ghcr.io/socfortress/copilot-frontend:lab - name: Notify Discord uses: appleboy/discord-action@v1.0.0 diff --git a/backend/app/incidents/routes/incident_report.py b/backend/app/incidents/routes/incident_report.py index 4fc2c578..3f6963fa 100644 --- a/backend/app/incidents/routes/incident_report.py +++ b/backend/app/incidents/routes/incident_report.py @@ -17,7 +17,7 @@ from app.customers.routes.customers import get_customer from app.db.db_session import get_db from app.incidents.models import Alert, Asset -#from app.incidents.services.reports import download_template, create_case_context, save_template_to_tempfile, render_document_with_context, create_file_response, cleanup_temp_files +from app.incidents.services.reports import download_template, create_case_context, save_template_to_tempfile, render_document_with_context, create_file_response, cleanup_temp_files from app.incidents.models import AlertToTag from app.incidents.models import Case from app.incidents.models import CaseAlertLink @@ -168,29 +168,29 @@ async def get_cases_export_customer_route( return response -# @incidents_report_router.post( -# "/generate-report-docx", -# description="Generate a docx report for a case.", -# ) -# async def get_cases_export_docx_route( -# template_name: str, -# case_id: int, -# session: AsyncSession = Depends(get_db), -# ) -> FileResponse: -# case = await fetch_case_by_id(session, case_id) -# if not case: -# raise HTTPException(status_code=404, detail="No cases found") +@incidents_report_router.post( + "/generate-report-docx", + description="Generate a docx report for a case.", +) +async def get_cases_export_docx_route( + template_name: str, + case_id: int, + session: AsyncSession = Depends(get_db), +) -> FileResponse: + case = await fetch_case_by_id(session, case_id) + if not case: + raise HTTPException(status_code=404, detail="No cases found") -# context = create_case_context(case) + context = create_case_context(case) -# template_file_content = await download_template(template_name) -# tmp_template_name = save_template_to_tempfile(template_file_content) + template_file_content = await download_template(template_name) + tmp_template_name = save_template_to_tempfile(template_file_content) -# rendered_file_name = render_document_with_context(tmp_template_name, context) + rendered_file_name = render_document_with_context(tmp_template_name, context) -# response = create_file_response(rendered_file_name) + response = create_file_response(rendered_file_name) -# # Clean up temporary files -# cleanup_temp_files([tmp_template_name]) + # Clean up temporary files + cleanup_temp_files([tmp_template_name]) -# return response + return response diff --git a/backend/app/incidents/services/reports.py b/backend/app/incidents/services/reports.py index 9f51da35..0a5fefbf 100644 --- a/backend/app/incidents/services/reports.py +++ b/backend/app/incidents/services/reports.py @@ -1,81 +1,81 @@ -# from typing import Dict -# from fastapi.responses import FileResponse -# from tempfile import NamedTemporaryFile -# import os -# from docxtpl import DocxTemplate -# from app.data_store.data_store_operations import download_data_store -# from loguru import logger +from typing import Dict +from fastapi.responses import FileResponse +from tempfile import NamedTemporaryFile +import os +from docxtpl import DocxTemplate +from app.data_store.data_store_operations import download_data_store +from loguru import logger -# async def download_template(template_name: str) -> bytes: -# """Retrieve the template file content from the data store.""" -# return await download_data_store(bucket_name="copilot-case-report-templates", object_name=template_name) +async def download_template(template_name: str) -> bytes: + """Retrieve the template file content from the data store.""" + return await download_data_store(bucket_name="copilot-case-report-templates", object_name=template_name) -# def create_case_context(case) -> Dict[str, Dict[str, str]]: -# """Prepare the context for the Jinja template.""" -# return { -# "case": { -# "name": case.case_name, -# "description": case.case_description, -# "assigned_to": case.assigned_to, -# "case_creation_time": case.case_creation_time, -# "id": case.id, -# "alerts": [ -# { -# "alert_name": alert.alert.alert_name, -# "alert_description": alert.alert.alert_description, -# "status": alert.alert.status, -# "tags": [tag.tag.tag for tag in alert.alert.tags], -# "assets": [ -# { -# "asset_name": asset.asset_name, -# "agent_id": asset.agent_id, -# } -# for asset in alert.alert.assets -# ], -# "comments": [ -# { -# "comment": comment.comment, -# "user_name": comment.user_name, -# "created_at": comment.created_at, -# } -# for comment in alert.alert.comments -# ], -# "context": { -# "source": alert.alert.assets[0].alert_context.source if alert.alert.assets and alert.alert.assets[0].alert_context else None, -# "context": alert.alert.assets[0].alert_context.context if alert.alert.assets and alert.alert.assets[0].alert_context else None, -# } if alert.alert.assets else None -# } -# for alert in case.alerts -# ] -# } -# } +def create_case_context(case) -> Dict[str, Dict[str, str]]: + """Prepare the context for the Jinja template.""" + return { + "case": { + "name": case.case_name, + "description": case.case_description, + "assigned_to": case.assigned_to, + "case_creation_time": case.case_creation_time, + "id": case.id, + "alerts": [ + { + "alert_name": alert.alert.alert_name, + "alert_description": alert.alert.alert_description, + "status": alert.alert.status, + "tags": [tag.tag.tag for tag in alert.alert.tags], + "assets": [ + { + "asset_name": asset.asset_name, + "agent_id": asset.agent_id, + } + for asset in alert.alert.assets + ], + "comments": [ + { + "comment": comment.comment, + "user_name": comment.user_name, + "created_at": comment.created_at, + } + for comment in alert.alert.comments + ], + "context": { + "source": alert.alert.assets[0].alert_context.source if alert.alert.assets and alert.alert.assets[0].alert_context else None, + "context": alert.alert.assets[0].alert_context.context if alert.alert.assets and alert.alert.assets[0].alert_context else None, + } if alert.alert.assets else None + } + for alert in case.alerts + ] + } + } -# def save_template_to_tempfile(template_file_content: bytes) -> str: -# """Save the template content to a temporary file.""" -# with NamedTemporaryFile(delete=False, suffix=".docx") as tmp_template: -# tmp_template.write(template_file_content) -# return tmp_template.name +def save_template_to_tempfile(template_file_content: bytes) -> str: + """Save the template content to a temporary file.""" + with NamedTemporaryFile(delete=False, suffix=".docx") as tmp_template: + tmp_template.write(template_file_content) + return tmp_template.name -# def render_document_with_context(template_path: str, context: Dict[str, Dict[str, str]]) -> str: -# """Load and render the document template with the given context.""" -# doc = DocxTemplate(template_path) -# doc.render(context) -# with NamedTemporaryFile(delete=False, suffix=".docx") as tmp: -# doc.save(tmp.name) -# return tmp.name +def render_document_with_context(template_path: str, context: Dict[str, Dict[str, str]]) -> str: + """Load and render the document template with the given context.""" + doc = DocxTemplate(template_path) + doc.render(context) + with NamedTemporaryFile(delete=False, suffix=".docx") as tmp: + doc.save(tmp.name) + return tmp.name -# def create_file_response(file_path: str) -> FileResponse: -# """Create a FileResponse object for the rendered document.""" -# return FileResponse( -# file_path, -# filename="case_report.docx", -# media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document", -# ) +def create_file_response(file_path: str) -> FileResponse: + """Create a FileResponse object for the rendered document.""" + return FileResponse( + file_path, + filename="case_report.docx", + media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document", + ) -# def cleanup_temp_files(file_paths: list): -# """Clean up the temporary files.""" -# for file_path in file_paths: -# if os.path.exists(file_path): -# os.remove(file_path) +def cleanup_temp_files(file_paths: list): + """Clean up the temporary files.""" + for file_path in file_paths: + if os.path.exists(file_path): + os.remove(file_path) diff --git a/backend/requirements.txt b/backend/requirements.txt index 946c1483..6f159a9f 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -110,7 +110,7 @@ prompt-toolkit==3.0.39 protobuf==4.24.4 psycopg2-binary==2.9.9 pyasn1==0.5.0 -#docxtpl==0.18.0 Comment out for now +docxtpl==0.18.0 pycountry==22.3.5 pycparser==2.21 # pydantic==1.10.13 From 865de633a2f58d53a94167f291d3edeea7dca0b7 Mon Sep 17 00:00:00 2001 From: Taylor Date: Mon, 14 Oct 2024 08:45:33 -0500 Subject: [PATCH 26/42] `chore: Bump typing_extensions to version 4.9.0` --- backend/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/requirements.txt b/backend/requirements.txt index 6f159a9f..e2136a77 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -164,7 +164,8 @@ tqdm==4.66.1 typer==0.9.0 types-python-dateutil==2.8.19.14 typing==3.7.4.3 -typing_extensions==4.8.0 +#typing_extensions==4.8.0 Bump to 4.9.0 +typing_extensions==4.9.0 tzdata==2023.3 tzlocal==5.2 ujson==5.8.0 From 3520e3c563f73202d9077fc3cdb66d4d1b7137de Mon Sep 17 00:00:00 2001 From: Taylor Date: Mon, 14 Oct 2024 13:04:23 -0500 Subject: [PATCH 27/42] CaseDownloadDocxRequest model --- backend/app/incidents/routes/incident_report.py | 13 +++++++------ backend/app/incidents/schema/db_operations.py | 12 ++++++++++++ backend/app/incidents/services/reports.py | 7 ++++--- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/backend/app/incidents/routes/incident_report.py b/backend/app/incidents/routes/incident_report.py index 3f6963fa..32aea897 100644 --- a/backend/app/incidents/routes/incident_report.py +++ b/backend/app/incidents/routes/incident_report.py @@ -3,6 +3,7 @@ from io import StringIO from typing import Any from typing import Dict +from typing import Optional from fastapi.responses import FileResponse from typing import List import os @@ -21,6 +22,7 @@ from app.incidents.models import AlertToTag from app.incidents.models import Case from app.incidents.models import CaseAlertLink +from app.incidents.schema.db_operations import CaseDownloadDocxRequest from loguru import logger incidents_report_router = APIRouter() @@ -167,28 +169,27 @@ async def get_cases_export_customer_route( response.headers["Content-Disposition"] = f"attachment; filename={filename}" return response - +# ! TODO - Should I enable other doc types? # ! @incidents_report_router.post( "/generate-report-docx", description="Generate a docx report for a case.", ) async def get_cases_export_docx_route( - template_name: str, - case_id: int, + request: CaseDownloadDocxRequest, session: AsyncSession = Depends(get_db), ) -> FileResponse: - case = await fetch_case_by_id(session, case_id) + case = await fetch_case_by_id(session, request.case_id) if not case: raise HTTPException(status_code=404, detail="No cases found") context = create_case_context(case) - template_file_content = await download_template(template_name) + template_file_content = await download_template(request.template_name) tmp_template_name = save_template_to_tempfile(template_file_content) rendered_file_name = render_document_with_context(tmp_template_name, context) - response = create_file_response(rendered_file_name) + response = create_file_response(file_path=rendered_file_name, file_name=request.file_name) # Clean up temporary files cleanup_temp_files([tmp_template_name]) diff --git a/backend/app/incidents/schema/db_operations.py b/backend/app/incidents/schema/db_operations.py index 0bf62cda..7cff124e 100644 --- a/backend/app/incidents/schema/db_operations.py +++ b/backend/app/incidents/schema/db_operations.py @@ -14,6 +14,7 @@ from app.incidents.models import CaseAlertLink from app.incidents.models import CaseDataStore from app.incidents.models import Comment +from pydantic import validator class SocfortressRecommendsWazuhFieldNames(Enum): @@ -355,3 +356,14 @@ class CaseReportTemplateDataStoreResponse(BaseModel): success: bool message: str +class CaseDownloadDocxRequest(BaseModel): + case_id: int + template_name: str + file_name: Optional[str] = "case_report.docx" + + @validator('file_name', pre=True, always=True) + def ensure_docx_extension(cls, v): + if v and not v.endswith('.docx'): + return f"{v}.docx" + return v + diff --git a/backend/app/incidents/services/reports.py b/backend/app/incidents/services/reports.py index 0a5fefbf..6aa3831a 100644 --- a/backend/app/incidents/services/reports.py +++ b/backend/app/incidents/services/reports.py @@ -3,13 +3,14 @@ from tempfile import NamedTemporaryFile import os from docxtpl import DocxTemplate +from typing import Optional from app.data_store.data_store_operations import download_data_store from loguru import logger async def download_template(template_name: str) -> bytes: """Retrieve the template file content from the data store.""" return await download_data_store(bucket_name="copilot-case-report-templates", object_name=template_name) - +# ! TODO: Make this more modular ! # def create_case_context(case) -> Dict[str, Dict[str, str]]: """Prepare the context for the Jinja template.""" return { @@ -66,11 +67,11 @@ def render_document_with_context(template_path: str, context: Dict[str, Dict[str doc.save(tmp.name) return tmp.name -def create_file_response(file_path: str) -> FileResponse: +def create_file_response(file_path: str, file_name: Optional[str] = "case_report.docx") -> FileResponse: """Create a FileResponse object for the rendered document.""" return FileResponse( file_path, - filename="case_report.docx", + filename=file_name, media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document", ) From b69cf6308f2d454b6f5d18c5ff6166fb09256806 Mon Sep 17 00:00:00 2001 From: Taylor Date: Mon, 14 Oct 2024 13:04:54 -0500 Subject: [PATCH 28/42] chore: Update branch name in Docker workflow --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 4dc403cb..9f2904c2 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Docker on: push: - branches: [incident-reports-docx] + branches: [main] jobs: build-backend: From a7420d7412215343c5f28f47c23698b1b7eccad0 Mon Sep 17 00:00:00 2001 From: Taylor Date: Mon, 14 Oct 2024 13:30:39 -0500 Subject: [PATCH 29/42] `chore: Add endpoint to list case report template files` --- backend/app/data_store/data_store_operations.py | 11 +++++++++++ backend/app/incidents/routes/db_operations.py | 12 +++++++++++- backend/app/incidents/schema/db_operations.py | 5 +++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/backend/app/data_store/data_store_operations.py b/backend/app/data_store/data_store_operations.py index a9d2190b..aaef8def 100644 --- a/backend/app/data_store/data_store_operations.py +++ b/backend/app/data_store/data_store_operations.py @@ -4,6 +4,7 @@ import aiohttp from fastapi import HTTPException from fastapi import UploadFile +from typing import Optional from loguru import logger from app.data_store.data_store_schema import CaseDataStoreCreation, CaseReportTemplateDataStoreCreation @@ -99,6 +100,16 @@ async def list_case_data_store_files(bucket_name: str, case_id: int) -> list: objects = await client.list_objects(bucket_name, prefix=f"{case_id}/") return objects +async def list_case_report_template_data_store_files(bucket_name: Optional[str] = "copilot-case-report-templates") -> list: + client = await create_session() + objects_list = [] + logger.info(f"Listing objects in bucket {bucket_name}") + objects = await client.list_objects(bucket_name) + for obj in objects: + logger.info(f"Object: {obj.object_name}") + objects_list.append(obj.object_name) + return objects_list + async def create_buckets() -> None: await create_bucket_if_not_exists("copilot-cases") diff --git a/backend/app/incidents/routes/db_operations.py b/backend/app/incidents/routes/db_operations.py index 1820effd..f8bb77ef 100644 --- a/backend/app/incidents/routes/db_operations.py +++ b/backend/app/incidents/routes/db_operations.py @@ -56,7 +56,7 @@ from app.incidents.schema.db_operations import MappingsResponse from app.incidents.schema.db_operations import NotificationResponse from app.incidents.schema.db_operations import PutNotification -from app.incidents.schema.db_operations import SocfortressRecommendsWazuhAlertTitleName +from app.incidents.schema.db_operations import SocfortressRecommendsWazuhAlertTitleName, CaseReportTemplateDataStoreListResponse from app.incidents.schema.db_operations import SocfortressRecommendsWazuhAssetName from app.incidents.schema.db_operations import SocfortressRecommendsWazuhFieldNames from app.incidents.schema.db_operations import SocfortressRecommendsWazuhResponse @@ -154,6 +154,7 @@ from app.incidents.services.db_operations import update_case_status from app.incidents.services.db_operations import upload_file_to_case from app.incidents.services.db_operations import validate_source_exists +from app.data_store.data_store_operations import list_case_report_template_data_store_files incidents_db_operations_router = APIRouter() @@ -808,6 +809,15 @@ async def delete_case_data_store_file_endpoint(case_id: int, file_name: str, db: async def get_case_by_id_endpoint(case_id: int, db: AsyncSession = Depends(get_db)): return CaseOutResponse(cases=[await get_case_by_id(case_id, db)], success=True, message="Case retrieved successfully") +@incidents_db_operations_router.get("/case-report-template", response_model=CaseReportTemplateDataStoreListResponse) +async def list_case_report_template_data_store_files_endpoint(db: AsyncSession = Depends(get_db)): + logger.info("Listing all files in the data store") + return CaseReportTemplateDataStoreListResponse( + case_report_template_data_store=await list_case_report_template_data_store_files(), + success=True, + message="Files retrieved successfully", + ) + @incidents_db_operations_router.get("/case-report-template/download/{file_name}") async def download_case_report_template_endpoint(file_name: str, db: AsyncSession = Depends(get_db)) -> StreamingResponse: file_bytes, file_content_type = await download_report_template(file_name, db) diff --git a/backend/app/incidents/schema/db_operations.py b/backend/app/incidents/schema/db_operations.py index 7cff124e..4b337262 100644 --- a/backend/app/incidents/schema/db_operations.py +++ b/backend/app/incidents/schema/db_operations.py @@ -367,3 +367,8 @@ def ensure_docx_extension(cls, v): return f"{v}.docx" return v +class CaseReportTemplateDataStoreListResponse(BaseModel): + case_report_template_data_store: List[str] + success: bool + message: str + From ac2b7ac9852029ac0214dd401ba5d7fd844610d0 Mon Sep 17 00:00:00 2001 From: Taylor Date: Mon, 14 Oct 2024 14:19:17 -0500 Subject: [PATCH 30/42] `feat: Add endpoint to create default case report template` --- backend/app/incidents/routes/db_operations.py | 11 +++++- .../app/incidents/services/db_operations.py | 37 +++++++++++++++++- .../templates/case_report_jinja_template.docx | Bin 0 -> 98517 bytes 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 backend/app/incidents/templates/case_report_jinja_template.docx diff --git a/backend/app/incidents/routes/db_operations.py b/backend/app/incidents/routes/db_operations.py index f8bb77ef..3fa9ee53 100644 --- a/backend/app/incidents/routes/db_operations.py +++ b/backend/app/incidents/routes/db_operations.py @@ -124,7 +124,7 @@ from app.incidents.services.db_operations import get_case_by_id from app.incidents.services.db_operations import get_customer_notification from app.incidents.services.db_operations import get_field_names -from app.incidents.services.db_operations import get_timefield_names +from app.incidents.services.db_operations import get_timefield_names, upload_report_template_to_data_store from app.incidents.services.db_operations import is_alert_linked_to_case from app.incidents.services.db_operations import list_alert_by_assigned_to from app.incidents.services.db_operations import list_alert_by_status @@ -818,6 +818,15 @@ async def list_case_report_template_data_store_files_endpoint(db: AsyncSession = message="Files retrieved successfully", ) +@incidents_db_operations_router.post("/case-report-template/default-template", response_model=CaseReportTemplateDataStoreListResponse) +async def create_default_case_report_template_endpoint(db: AsyncSession = Depends(get_db)): + logger.info("Creating default file in the data store") + return CaseReportTemplateDataStoreListResponse( + case_report_template_data_store=await upload_report_template_to_data_store(db), + success=True, + message="Default file created successfully", + ) + @incidents_db_operations_router.get("/case-report-template/download/{file_name}") async def download_case_report_template_endpoint(file_name: str, db: AsyncSession = Depends(get_db)) -> StreamingResponse: file_bytes, file_content_type = await download_report_template(file_name, db) diff --git a/backend/app/incidents/services/db_operations.py b/backend/app/incidents/services/db_operations.py index a640065a..ecc94b26 100644 --- a/backend/app/incidents/services/db_operations.py +++ b/backend/app/incidents/services/db_operations.py @@ -5,10 +5,14 @@ from fastapi import HTTPException from fastapi import UploadFile +import os from loguru import logger +import io from sqlalchemy import asc from sqlalchemy import delete from sqlalchemy import desc +from pathlib import Path +import mimetypes from sqlalchemy import distinct from sqlalchemy import func from sqlalchemy.exc import IntegrityError @@ -41,7 +45,7 @@ from app.incidents.schema.db_operations import AlertTagBase from app.incidents.schema.db_operations import AlertTagCreate from app.incidents.schema.db_operations import AssetBase -from app.incidents.schema.db_operations import AssetCreate +from app.incidents.schema.db_operations import AssetCreate, CaseReportTemplateDataStoreListResponse from app.incidents.schema.db_operations import CaseAlertLinkCreate from app.incidents.schema.db_operations import CaseCreate from app.incidents.schema.db_operations import CaseOut @@ -1875,3 +1879,34 @@ async def download_report_template(file_name: str, db: AsyncSession) -> Tuple[by file_content = await download_data_store(file.bucket_name, file.object_key) return file_content, file.content_type + +async def upload_report_template_to_data_store(db: AsyncSession) -> CaseReportTemplateDataStoreListResponse: + current_dir = Path(os.getcwd()) + templates_dir = current_dir.parent / "backend" / "app" / "incidents" / "templates" + + templates_list = [] + + for file in templates_dir.iterdir(): + logger.info(f"Uploading report template {file.name} to Minio") + if file.is_file(): + if await report_template_exists(file.name, db): + raise HTTPException(status_code=400, detail="File name already exists for this template") + with open(file, "rb") as f: + content = f.read() + content_type = mimetypes.guess_type(file)[0] + upload_file = UploadFile(filename=file.name, file=io.BytesIO(content)) + await upload_case_report_template_data_store( + data=CaseReportTemplateDataStoreCreation( + report_template_name=file.name, + bucket_name="copilot-case-report-templates", + object_key=file.name, + file_name=file.name, + content_type=content_type, + file_hash=hashlib.sha256(content).hexdigest(), + ), + file=upload_file, + ) + templates_list.append(file.name) + await add_report_template_to_db(upload_file, len(content), hashlib.sha256(content).hexdigest(), db) + + return templates_list diff --git a/backend/app/incidents/templates/case_report_jinja_template.docx b/backend/app/incidents/templates/case_report_jinja_template.docx new file mode 100644 index 0000000000000000000000000000000000000000..227dc73f75d8a1555245c58bbbea7800604f226a GIT binary patch literal 98517 zcmeFabyS<(wl5qUiWhf>7N@vdvEoi~cc-{Rixw#qDO%j!-Q9}2dvOh(8`^ijd!M`a z9pCx>x_6AzjED9~vNCPW-<(V4N))7_pfLfk0C)fZKn6JWskEGh0077l0RRjDJfxPW zo$Ut`+Yfpw?)D~5I*e{M)})!xkgvW2Ai?ebJpKn;U^rgSYLOYUXBF-qMZAnkZ6Si? zU5bG9@}`;woTqB`!P}|3zz?w;t3K*3hT;dk7DNfHxb(|Tqw?|P$A>>VROVqtrbe+3 z`O+(qia)$tH0gL+dP?*%dH>cRE_K-wg z)Ogc(IG=?)kfo15HDgGx;Y{x1Fs6!?b9HQW>{Oj7ggJkjzk)*Mq+DTqe_c`_tq3zo zy+6ryq5_@2K@ob|I-x{5auJ~#RZq>EoAT9JR@;JPEPw6W$NGKK%rmG$whO))Ibe7# zsX5Gi1pJLMZs7)y@l|PxHi6Pkunmve?x2#i`PIM(91WTHf|m03(P#99A5uJz9o8kDWaPGV zA$c_BUiX_2U!aWuhbf-u#|CGfY+;~bPvLjFKX?d@I5iJ+;ma*4gIb)JI$wMYV15AI zeEiNLU`ZlAVD~v{nB>XM$6H`KR1C%l?XcLBEP8>|Jgv($vz8lED(*^5$VSzzrxK{6 zpd|mG$SIU8ITJVwSD>o&T{mfYNt34Wfv3}bd3_WFMm-1w1yJ}e@!*@P56lzT$=AVf zM+Cy6+CKiq0gr5KYtdvAL;tRK60fm|Q_BEm~`E*H{X8Co=kD zk4W8q4LbSm-0-oRLdy2tBU;QLW&-V=SSOL;1i#k1PpF6IvIkjI1ATJ_q>my*n}zgt z%ul95{04<31*EnkSou3>H<-0{i^3Nzv%Euck$nEmI4(gWgyA&)m)qJ~QxuGP=b@7tjM6I_M|7?O%e0DyoV0013qBUd{|V{)gwz?aPX<8(*gTO|3mVwH z*y0<|kxGh$NiH#dPsaRn`vXVlqr-Z^rad08_@YAitO*_|3%C5RXQpVd7|c&BXtyY& z%px&vNMbE`VLha(QGR=_5D|e zCpp}Ej~B$7Fgpil9t6t}Ym)LhT~|vVP?;UBp|hGg?uan`)y$yND_1_Z8~B*d6Pu(e zbjsH)a=jv1TuogRofs0k-|TDnbktI+^&{19-u)-leu2#c{tDJeT$Z7*c9-EIlowK< z@xHj((OMf0GA5%uX;T7j`9+Iz3q85+Ys;|$j-13G&-U49-xS_ex>vqGn zHrOe(f$o{zaCA4Vo30f*0S(=BabpO6UeN7H*K`p*2!Voz`a3NjL6UOENAS>TaEJ))+Q zw-YoH?pNqS#f*MQ>3&sdAMWU%A#cD~AjKv+`v)wpM*Rsz)ZNV%?D7P7@L#cj$F}Z|bQGeZUI&dxWj)XF+ zk~ndQxwT@6k|;pePVpU2UQ)X=jrj{ff$I|zjM*r@CIaewTLWoVmuVLqX(53DH2SVs zHV03mIcd&vzlyh5EkCpu)xJyt*EvdHDvuyc1C#WLKE8(=Zq1W;1yx#2@hPN)9zcn( zqoJ?GxIvdQUjI=UlTb@VVA44@OZWPeNX}X%va|aWY?}wQdbp_mDMk5ASa0JlW55{o z+IJ$Tr?fW;=Sz38giLR@Td!^!TG!86l!buxn_Qu(K0EfO0sMlr4diA>#A7-Xv~2AX zqMWm32RJiaK*>$MsJrHV@4~u!#M=Xan*c1jm&rfp1O^?PqA?m*reiDwOT;u;^>HNl?@x`yZF7(G8VY`khiUg#(m4 zxLplNd;;W1Lb6eC2Bhhro9u{sq%g)8fK44+|U4AOKW$2S;{#HZE z55R-tR#oH3z?`oi7ob(adaxF13=7T~~H3jm!2nJ9eXmj#jzUCBxrZkRG5RuJc{}uMPzFmw_ z_CuVMADy8f8ExM0eM?sQd#Guy=;kJ=oH%2iIotj05I;&&giJ*cL`*kdOOV_-`tC$W z3o5^)S(ou|_>?M2f=Zv{n+aS@Mk^;e=G7-+j+55EeA>tQZXd)pjA};X8p09fjzS#wS$8IX z$>mQ6H=lN|tQE=|n z(IvsjmR0TA9)nu1rdE!pN~7V>1EuQZUN;2VX;S&oa*KR z7a!vZz?TCK_V^q(Y&6Bvf6c(vo(-@ZVoxu=xZ)EAMEOUd&B8SC=KCDKKz|LzRiA<_ zhk`mTupBw{_Dgo!D~9eQc-@*b8Ag<2fR8yZ|8xvby~SF z8~&AW8|TK?cuEV6iiwRhpR8BE7)1=-p98~{|uvEFq zOvJ*ERMk1U@F!`4GIMzq0o#$yyV+ebS-P(lXj5>d#u)M?;L{7pL$@xj&k4#ClPa?p zBPjEA3;XX(9mO!n-FcVBC_`DaXZFSi1d5dr4JNvP`dw3e^oc=K@-5;{HLNtvLS*e7 z`BmRcJNy+l#1v!?x|(Az32PJy9K*_x#4FRxw0$v73CBh-+E!m$J07~)6v*0fRxLB9 z+83oZX~NrBM*$87rZ|!byp)q(6^}t()8WR~boa$lP0W1{L$|N|$F=XPTnT zQIhbosGoREm2O?NtP7gfkd4&*NTauz=6KbT4)XHEi?YK^%gkZzwjBA>`Lqv)m13?r zYG?!$PzMOr!Q69|+b@%SgxBlEsZ+laP2;Fp9MdB9S)5;MUR3*65NsMq76mo)sW>j6 z(|Qk)ezT*qSDmA)fP#k;k-b&i-?Sk?vLe@rsIFl-l zG>nJN?|9=s{WC+}8-!AS5!F6$@aDs#=sWm0nvlJW zUBz5v5`BeN<=oU;8Bj9m$H5tgZrZ0}eEjB?TYy6772f2NQjI}cuBC#2{(7^fAltzB zO8b4&d|F1tfB;@mcO-Q4%2oNdSm~Rul&^JOn9W$nUYg~81bA-RD5Z+Wx*Mf(c9x{o z1reDA2XBRx;C`8(KWEfcQs*8~$u$ZKk%}`qO-fmq9&9(hGM-=B8u1D<=!h2eYaAH% z#9~PMcHX=E!br0!xhQ4T1>TeOrM3er37m|Tf>gjv;=+(M-Ta`65%>FdN7f|MaELLp zrxAWfH0z~n>!lX=i%5deGuj)tm5uxC*chfX4Muq@SeLLw3bCI`h^qa$r5D^@<62vo zrgF?G2chJNH)&d3F_WqxlfU(o{iHwg)12LMu)v=MkA)4kMaFjaBDa+7eo+$n+m|=9 z%<7zuN&WbX6)C`gqkIG7M0;~<7)KK$!=i2@erT@21yS~b>=tUB`QieE{MECXX?x1i zZNd|$l$xw8A3HU?S!Ms)xsjMui4q&u`B|5)s|AA346*wz%cX3a;ba(O>OEUK`Yxjb*MX$u?LA z%<>6M!b@kt;X=;0#AdSgX~TT3stK^M9T_j*F>q*Kv9*r9{#iX`sIHQezfPo~Ln(qJ?n^p&drSD#q*Te}F6%Otz`~zHxOHc|Sq`O#u%{7vK6^P1CkM2hbUlkU+j z7G4bZlg*<=tqyCi)6+{U3gU8WC1sZszBM`()D~8sI#;0JXe`iv+3;#SiSW;@HR?K= z3b4qFchJ_0Y^GG~n&J&f6Wz$w+r=9pG2HSmvp-m<9N&^uJc*#o`9X}C$(gcy>l1~l z`B+;uC>|fl3MZ(iue~)9M;nYhKV5iC*n(z zd)d52D9J}ykSejFW(~{tqIr}u*N|G@8olI>2urGpv=-}YNu||FShysW+6F#X*4uD& z;G@)TG|!gInp&rhR^38|-!7X50=ll#bd`gL548wvs+I9P=Co?#^edsLjlRYw>a!XY zQN~6PusdzO#PVcWh&7Hrym!)B&ULp@s!+yHS1S;Szc+|+s4&tmLa*B4B-xEm%PWp1dXO4ZuhMab!>$)%wJg9@CW@1={SqW+Mp z)8EG!6#8w7z_@VfFjRe5z6-l$W&B4p1KFyo257@M3G>opX4_xcS%1|c-;bx!GS2f<6YW2iOi?Ki1JC+bfC zUH*kWp}HS{`|wF>Sgz>Ee&uHF^^AG zvQ4XY|K5W=?>7%a5X9BbSmLRy$Ef_lFj4_+!k1YgdkSNhQAXTGg8Nzwj!jR4&@p?WS|oiCvxrP4g-H!JF9)_ zi)38Nn>=4a+4t2EEuFAQiAVFN(ohKE55oE&F8m*)WTSC<%o+Nk<*+Mb<9-VTCB9M&>~P)EAE8-b?Tx^kyRO52UjFpSX!MvjZ)oRQjz0*FA!;lXnS(N6rmq z6wSe!oa1`R{~~4>V2Y`;w1j^6|Oj zW4wkm#wuk9I+}o*yw_@hq{F$32B|1&FEfZ2-rG#ai$oPmAkCyWDmq1zwhz063crcs zIe06NAIn!1ftpN>RaV#{5J59utNC*sv5Z%3x;Yhb`2~|ks)srvkCE-zNx}!egA|no zJGM5B;AT}j+pnp5c(6Q)*^1&L;Ge;%qJybY|Yi$Ed1VNkkyn95>fYDCfPd zTf7RkNFC@^ok>xjG4`D=jWLemOYDt4R12?1o-xB%^R)Q5R3z0KBKH%qK{O^e=2oa^ zfYu$C64~YF##Ndip@n}E5w0KsLYm}3;Xar2D6r@lm!Rni2J*7;GIs?YA4B!viWiwQ zal}~{2Uuijwtu;s(P-0<8c|<*G9{J9I@f_R85pdEC(p?2)Y)CMK74vG^m^zm%$lyk zwSzKxB8Nate~z)e8jtP-mI?nj3V-Q%r)5li)l5;G$X3?q(qSUXd~){tlAoili?r0h zEe!*EXI>G%>3AjD>DZS#Wt1L9m7}n3&HK4I4IC$*STMv@;|S4goWuz=a~9Nezl|6Z ze-zF9_U;UcVoOL{CFn!Bb}~1lHk(6>-dTcNrZTHV%aQc5K}|=V^{3+q?%wi(=7wqP zMa|l5d$HcrGr2GCKCtV2>Goee5LT%gu$URSP8K0CoY?z82CS+#b-O8!o$_+boBIfH z={H^htFc%rnR5(}$axvLG6VT4eypdRv^}lxx)T#dU!@fjDi&)-cKZ~oZLOF69b&_i zKG6=cFKhJmC;CMKXJfg%(($q@qX0-0z1fU{pz1!(qA;oRkqqyAje~|sJxZv_)R3WV zp}t;2W&&C&pWQ*Dx}9GBmIC!D5hJsEYgPjnC_BQ1;&;xxowPKTSKIlzW^^{%l}A)& zs-4;M2W+{zaXACM?eiZ##IM>Gdk=ldD{PYqK|lQvZervzN0{8V?4^^Quff~JAYA0y zv@FV*2)o0PKMJQ3RwFf`nO`evbxH3s6JcqT^Dpri5R4Bg4N5^``Wdw?lDM}ZfE`MLjAvV>*~1}APuA2 z2SFMT``6;wh52W6;0s=y7C{=U;O(6|Af7rP+7oVW_MCxljdrg$vDd)YNyUVKEd=;# zy=Q2bk39EWFm;4vctr_iu7TKADl9{YdRa zT=%YsEL9;UuVOpxZNuDfC2H*hXmYtpR|n%LagDa^xSHXn1OwGbJ5qh~V0(@jHtm}< z1n|0COQ(=q9?6kxNfW{m=;jci%1EkaoS-~$S9W8eJFql2D?d}(Yr3i4I@OB_EwG0I z@%sET;(-Ps53lda5vMvhYVB?)ZlVwbnh`|Y3*Zp7WXPFS?F~r!POCQ2+mK+eUajE@ zLA}nGi!%0~QqO|nWhSv7K7}aX=$Yr4_Gcgk5<}po5p+b0aM>odh7Q%*wSPiXfm2+{ z3&>fKnNaSh*yz`TEDCueis72l9qP)Kqu|=yjo^x@Fo#J65s?KkhE^@*68`3fM)+`Z z$*<4#L2_STo15`7-OKP2BJ!il(2$<6v+v~{Y_-Zx?j#fD#7w?pFd*9$q1wv|-lKSy8xPY-6Q0 zl^d#jM7UtUJryiYw5J;}^6QsKJenTMq2tcZm(%%ukw31~vkGfbfEkifX??ec?xA^E z40MBavAjuWX%3-j**6ECe%tK~l~6;GHi%DCS(uA=_%$+uLmmNMOJ?z~G)|SIf+NFr z!V9cg9QTiU6?bGRzP3=0AljGd_dJuFIk{dJGol=t-^E~X3as2WBFmVDCIg2Pw)YdA z$>euG-QthCc|apce|b?NGT(*^QG%XHI|y_Fp+wlXc>I88G(Dh-u;)YdwiLk&&7tg` z3r^O$aUL5QDLMV@<91Mo)K=cPB8{f48J7C96sX|PtOjTW503md%vv{qwp16(+=M*7 zoI6ikD-f|RCCTY(q=XW$GTQ|eNK;7jA?24>x%h{E?6%oFeuQ*agJ}h6AIXmPBqUtd zWfh#lBRAB`-ZIu+=Aqx0U=ECJUMI5;mGvG-Yi`5EqaxEQn1*B(K`!MB@Q-?OeAJ#pk49Qd6 z0D<#C>r7=Wt327O3nX_F)(;#UJ0ovS{SHNhedsEg1}60ijMHjuR#Te=C-w9w+sfum zOya09uZ8;&7%%v6(_M%cPfT3e@Gd#uDA||Y^WxER*N%hEZ^Y+sdg^^xKaiwKdM8ey z#@;0-t4OYtS;~!MZQQVW(|dp{;^V%;#~ZSlLom_Py_Qarlq@SRrVrliJaP26MsD(| zstD+<$!&gbMSOdI0q@(C3EH9b6%+#*>i03dsTY}SyN9#!y|wVj$uz_bGBLjuMnhmI z2&1-V2Kv;;43^_RewAxvy!Bssnl$R9QlvD7(B=1i%^cK$cP&Dq_j$i@D=#XP3|Cd5 z22QJH)kFp-Kv{C&ON`y}YSjd(hf50ew)!{QNG#QOFMI4qS?_H%3uf%aj{5K=GZ z;FThcvK&)PC`ec-28`q+u(^}u?4&{vnjX_oj0i{5s%Lj}1z#Y3=y`ngG39jf1`lVZ z1i24Ro4(Gd(-fr+pZ@#!kSO6w_iUJjra#GEWM|pS%hb~%qUmu4EfWrVk~FvS#;puR zuJo96t)Ro09U9JNLD~!lMUKSeYENfJIiQ@w{P}f zU{i4d+I6_%p*=XE$=Mc;Hpbf4wBoZ#1RqcY9;oZd1LQd2wX+sA@!9DblrcjN-x#z_ zh<}G`-8uQ%PtWdG2sa<5LiyYOViE z+(woeRjlgUG4U|g;d(W-FtOGcK*^v!phGF@9(>Mq6u$gqlM=UhmzQ9~o zp9YooE(&werLvu=y{;l=WJx5E36xJ1pG5*T?#rF4G}bCi7J{sPmU>yYC~kED-Dpxe zB<42R%NJfI)->kb=az;wmyw$t5r5I~aHZ9he``4zq~Of{`f4$|b!3N&=f;esVQX2# z>xO_QPv`V}s*%=hX|YGQBCL8HH_~p8SB!*9LAEQn_>emEG-VLW(?3`;Q3ln=RX%22 z>bfQXY1(Y@2dNP3q`&4G4DZkzooVNx^GAj^{Xp~U5PDx`p33hc$q1r|^pi);2CRx6 z(`WQnYe&h05&TU8tze$~;V=38}`9%Tp0NX7oJpJ4$D@;yf2=V;n?_}cSnXrDdn&_DL2tt-^p8z^ADwNU7#-4><6KQUY9e{NE{ZL94#i_U z`cCx`1m3s*_d=MeGajRl;1Zc21OR{#01xqNXa9FK%)jpM|D!Sn0$d>nZv8*|(foDD zHjo)j3>bHZ+JA3Iy01(&uM$^jqgQ756dausyox;m-2<1%v2)KU*{Fml1MV zIsES9P$gwH(!@|zxCx(vuh>X7`Bn=R8?nl zZ9pC%|kP=%j#M5n18+nnta z=<{*o8}H|ONhUhFlk08v4c34dC|aAIEa+5@RM*MBkl0ulq6BtNU zhKYKT{m!ivpKOC=~ELBjiz|&hHL=Fg-7PdWaS2QKa|)_McU6u*EZY zpe7yPA)(A?1e2E+!hhJ(lT9QY^nMxf5YxG9N}i}Shf3?ousm`Uo>@t%SZ82Rk4H{} zC8fF$#@ISEGP@-G%7FF)|0N})pd)o4b7>{ik#u11_m6~vj_qH>P1@LMd4m>Kl@@vQ zg7D|Wd@5Yn2IG8Xs!LFc3ee-ka1eYW-_vH42Oju)Hsr2rHyNG3hUmg>Ka=e1$~2Zi zggyVcHmUc!ZjD!x9@&2;Ai-nl=fujqIsFKhwPQ??h7^al#!2Qb{JL2_DJs&JdO|2 z9Q;?w6`(Urg{pDqU+i&O^XM3-Z+)FUsF@-0G2AOQVZ_H_r*NL;hK;6V!Pamv5Q$qk zhvGfJ4cu-iTGY*$@TgTc>I*{rUi!&MVShpD%v`yi{cbfQ>#91%TCJ+kQr3klR3(cl z%NOH)h3c-P6}KUmj4u3jDD(IRgew0Em*Af0hoZGh224%-QD&H{Hr>p?Bbmc_V?O6< z6PvT)heF?(=(EE8ovaYA;zOOroy=suQI-Cf!_)az*Kf`PMp+}4RX&;^*C>;+a7Vku zbM?~7EWz}X9HKXxqs6;<+vj@2oH&}{RuBC>c3>p@d&Hmi31=PyV?_mwmA`AbOl*z+ zhDvw5mfa#LX5T8!5wAvb-rQ)7T5REg$$>O`$s*kM#BQ|_F~7~NMbuM`J?p6W9T^wjHklz!G|VRoq24a$z0BM|MMQH|XQ3)Z z(yT(!q$rA12V0g%Oc$vkhir?4YJ7>Ggft8MYuae0uyxu>*&})lftUlc+A>HQq^Ygh z?+c@X_L(e^-pwDti}e-naMhse#8m$}QO!cuRlqEZSdv1FaU8(Ek#7m(cpIrQbLJaowd(h9EY zCS25mGGMO1==DUJ=9~jV{Z}cHu*WqnzntzS)x5Nnvu`@hFX5hF`fhes0AT=E-k!Z{ zqR6U-1+~G^#6WZOO^rS8bJ%wFQ75pZ8hWe)F1(;3Bj^%_ ziC4mfQuxx8U4$u|^%VT`b`|#;O5SmNI1CJrxJMNXWuG2@;I$XVTvY4lM}@k}MKh}= zZ0tGo)xTx>rf94*!aBdv06&+<{o#5$X>0Ayrr3sJlwYf+J@--WB21Fx)A}p&=(kDI z`i+O7>Cm=m%t2NCk^D)c+Yc-0K~9wQ9-I(Ao8xjV@$PZhAOpl#Dzd(Zg~%U>7< zS-szE?5*Z_@*fzP)*OCmkZwiC#6VcvdBMTDlr^q_GT<2Csdk)lf#j5{9N%=Xaa)q` z#7$$j6YjpZbc-sN7RS4=PE)$9s^j6wnBD5TxyqOaqRh@27S~)@OW88$I#fweL6g^nDY&jZno`GJNN}T26ZhRaQ0%kr_;H* zgS_J#=7(+K0vEf|HlKzC35!g^5Nw`>UE}TC-Ys;Ir0lOo-UE1wN<$G1lra4T%VB~-vNiBL_Hdu(qhD)gijiP`26Pa> z`jD`56R?Y_siI;=Li!gHTku3)jt-6VehCn;5Qt>kkHy}UY&q(_C(zzeY2Om3jYNJ> z)#|SBU^qtv?9P?r#Ira-=W<#xCx*_VhmjUiok}@!7(~{~m~%+shiNx_dZ|d{JKn3c zuZX3GY6CqI#DF-&fX<&NlT59KJfMR`EUjcuEAx##+Z@*Yt4JQbT@w_Ebl^a>|DnLU z_DHjcRRJIzaSf=Zww_iLj*z^qlxU20n*_t#PKcc$GXj@<{e+!>iqOTr?lgZYg>sf; z&I@1Y2h=b;(M^RpZg`Tvq-!HXFfyMSa$aHBb~$6kQ#If9xxl@dI zIhmNWU@Oay*7O`)J&pWq@seYn9Twrd=doV9i(^EEB=4}@C5+Ou_&*#u+nsQkmH+H= zUtqr6?dHqj3N9Uzx-7?1T2Da2>`-)CtL8F+Ib^ct;r$wQsjy&EawMw6RcqBSYcDp` zfhNwab^}oh{6JJ@_Jm*RHuFM{)2QU)MhlH8o=k(H9+p~Ay>z!n*|$}rE?2@NV%4sN zw0t~{C6_?kIQQhqZ9}`zO=bJkI1(>E$_2NT3W!Og($GJO`;d81@r@dP}pmPD?V`PuFECXoH!jp z-=fm}@tlD6JKvnL-?6@)DfK;SK*4%TEkihSd{UQJlyhJnC>Fr_dT*gc;YeV~7v$m^ z1{CLBWBA}TIItiaF<|tOP3m>uT@q_%cD$#PETx2Fo7usAfXjAp9bgKzo8XTn+8-Tf`?B~ z6C->RaN*%QUjoSXU5H;3#>8Jp25xo-!#$&8O&5%g=0d0qjTW3+EI%jfxk!^?ZNGgn zWLVZS0a0|f8faqbScJNep^v5p6AD`k3|~X6Kt(gF@1p2HjTZdo9JZQ?wx9OqjThKj zEoBaAfhCkMd7WPsMZ-+dBwl|QJg?~M=EE*C3J%d6J8`w$Fi!0kT`+}3YuKaZ*tG_CZS)2Y|S*W|L1Bz-w?9DA{c4re3rf?y5 zG=p3N)HMl8s?DH;2jl&b?qYDZz4f%?$$D74Xdn4#Mdz4(^W*e}!+pI!LF&<`vgC@E zx+_!|zc|KoUdYi~#oF13XM@^;>3HYqQd6Y!0cgL` z;Pf5r`D&%U2hX0LD|4uRT$a9=JolUzdK$oaA+5lLCCn(=K>3@? zDVB%vXl~8Sdej%xe)_@ws}i5G6wxbnuY{_kNKXqTlH@5`sv6AkU+=|YPf8l3W6D!p zMPi(g*uPhRh~+Kd;y5k14l%k?!{!7qmK&7Oo9!UUFj<1rLLCCJznb)#0Z&r7kajK` z>SPePx^2N*rGwS#yP2!4Og+>R*pc9GFiz5M<*8?L$5llQT@_a)l^khhu)t{n#o?=n zS+RK&RQkKXfnt9`ffw!myCaQ8>!|e4X<>v4naDom-uc+g=j_2K^8~p+SF9ReRQqPp zbQ2*MV+k(}GpT6p4k}q53f{vnZ3KNcTgtwPupSrTD;oFdGZhKY0T0qXWU-k`NHIFRm zbw`z$i@Mei%lhujhqacpke)KarmM0yCpw`-Qo|v&MU;FEqQ#lV3)FMw=a{6-(|E5> zM&?q5rZ6%AOz0jjZhKqdZMr};#9SEveKfPNKDQQ}2M)@qkx)i8SyHrGtQkJs>x^HW zz#dDm7YBUzNOvhtv&U!!pM(0_`Cov6@cbYHbf2X3KA-G({=)*l@@w{NV`6M!z+_=# zU}nO?Xm4v4svswU`~v^^Q^-=1Z1Np}9rbjsgi%vf zOnfDzel^6?PBMm4>esc8|M*b1daLR7G{DQ*b=G&X=77;aO<&r!Q`$if{HE{L({a$Ut0bTiKs4Ec*_wzTKf!+P!1 zXsos7(bAas^r(rA@X^B(_4FvWt>#hlPwIz@uEqN%m%F{|jv~vpT(P6o`{AC|-EiMp zJ%LDF_ocK)uarmnTtPEjkl%st-VKf>D5K5G?O=XLq7J2NKTAsxk%?saiJRHZfs{TN zgp9RXNF*lv+>JM=FYFt% zg0qP7f0)&3+FhltA8iV&a1d>UGb3ss(IXFWVy5Bx6x!v zueMXX`tflYd!r+~_B@=0&e_@Yp*Gr8P#At$)xxx=PCzYTvMhxafJ=TI?ikYGQ`!M% zon#mI%kpe(UI$Qf@xl}#XHaw0oRSI8VptG!kHK3j6Y34F?^re*VlfA8M%gVh1rz;Z zI%UA(Gc}3;u%6h@S_E%5UhHi2lJ%nMBRLe$_m71A(nG0nBaLK~71D_N=_ZwT`_##O zNblxy14PzdtL>f|_p43p&&%}^xEd!2z#y?AqQ3!yw)|K|=P;gz^v=2*rtxn_cyJwBFrFP!2wwE@$yrzev z)bC4+@A~qK+RyLxyJp*ug6*$Hz1J3U%KUU3Nzi`jb2s=X=%;gkYu9#BLvSW&>5Hx} zvwii~r%0jT%dH$%ouJ^OJAeB9q7*}|*W6du0))ejg@BgayaabCUDsteS z0vNsV16ZUqvHYf!WZg%y+NkGwg33${CKUwn_Lr;zVZfVzHWp~U`ra(}tJ|b7Mgfq< z`T&SG?wYzZzr@T&a0Pp*@V2*Ldp;7W5H;*?>3RBpH#~Q9J9zJ&`j>=D=iX0~vnxQT z&%*#nO2>opzv(gxY-#v{#UKWY(fjPb|CBu(m3wC89_sS|05aPE@JsN5C^?c9p2B}9 zoAWoBzr<5|{kP`fMSN4w44*&!vM=jg^Ow|=vegToK7JK=LVhYpq`!2N<=w^irw6M* zTNLxcF6a*;3koRKD%=6Eq`gDkz!xmvI~cs47PI*fc%-@L^Z1);8#<*wu`Hl zbC18cl;7AJ9q|jc&pp%q%QU&E5YYXdU~vq8D`T+$mf{!VJXGIx-G8$2s;{_CBhj~p zMI*(63i-u+@>xLx0E80QfoC57X2T4&+NXb&CcKDuYUKjz^T>Z)n5kGKU?qpcRT-gY5kjR|BYEX$;t{-*{|RrH31!t z$~p6YRQmtZ`2URtN12;Zs|`-iQTf?L2}ZiKB#b<6_h#13iB~*0k|gTVBP|}e=2N-E zBQ0*{+<*Ms8ZU`j*}B=(0x~(>ffGjRMQYhe3$2gKSad=-J+5LejGdLBlccw1`^TfSp_Xc zPn&wGv)x*rGm40%^9ozAXK3)F_J%Jm=t1LZHHXrbC1jW2jQJkK;uLWPPxnzWdl$tD zZD&vZd^`KIdx0)cjoTfc#(eW*DTY{*A8>+Zf5#PYW<@<(uz(jj6`%0 zD^rKUUj|`^F=n=nMsCCYcfV)a;G`ex`u?nW!i9Fr0*A_;yq`m4V)!l7d+QBI=8gx< zt*_Nk=qA*_!Ri;NkVqFyTdyFjM@vLk;m7CVfHn?HL4!sw*F3xk-Y$Y;$uCT>_?c_D zL!ek|F7bB2XI5yonO&5i>Q^;`CTh>05Pv~#1E#)KacQak+6`*XFK=6c!iJqD#?R)A zSZ1;R0{b_H!tHDtZ!CR}DqzcBmu8jP)V1zPJf6XoBOKf1$eIBlDw%&NUp=sqo$cuZ zSj0}~qzxvrpz9d{T1D~u$-ddMiv0(oVbN^f(0ul*xY;VMjk9|LX~gnh-=qb<$$BDvH&QA#A*c zFd#b@99^(~M+uHEcD{h7mwoAuuVRwUwP6p#cHh{L|I_j_UiVOQ?3`aztr)#w4rA>6 z%`yHdYmLj@=}h2)5u!f*Sx_5cOt!E)Ba{n6r08}uCGz0kR?eqdeFD5;_R9zNXt`A@ zOy@iGc{6<$qO&`{;7{~#OhCG`0*$)Yc)Dj$;$BFB1-tP(UpBd}#x$~bX_@6a}|L0bHw85*o zYT$+P+27j=e=iDY3IwI;ddWZ>27sseJ%G%h|GGGpvuy<4{m2GylQ^>Y<&*u_#UYDZ zT=1IGYw)guHh2x}_b$o55(blc0bYB;feOI~w|ia%`^WNCeAF|kKP>+*8CL0i>$)J1 z_YERYKLp&t;nw=VXZPS0?}+1X^j7e;hWPw*#^4GUMjfpz_-7QIp97u{c!L`N@H@u+ zbMwate>~w23jUzr4+{RE;13G^px_S*{(C4WhK^uNKqv1bp zjQ-pJ8vhsp>=J();bI%$c(*q*X4&@3R{;8!YMT<^dWB!lJQR0Op`L&L1OWIE^~U!f za}%Ghw_Shz%*kceFbVAQF(?4wJBi5?c)a7%VK5w&XvvsilmLQKUzq++m z)ihRWc?;wrG<9H`ItQ+sC09O}6+GQOcZ#txZ(W5|jT7f)L8_CbIxn1yYK@Z(4g-kz zeoWB&#FU%Jt(1$Y{^4L+(AWHW;OOyOfz_{EXNV@`C*Wm|UeV+8SwsLpxt1#oRVZQ7 zugnBsP^3#FBq!*;>sr_b&#@*8)nC+8Cu9i%J~tHd(eoBHKC7zFl;%ECKe_>~US)XI z?lzrxmGMm>ky_8H!bRtMv6tShg6sJKfGy|L3%{cKY}F@TeTq?J(jkz-qgXkFot7t4 z?L%9rr>6?2>A9UB<OX0@Z<^MFCSW!OaMQJNn880sA~4^_vWHD@u{MaIH_F%NW-ubR>>I>K8=j|? zCSQ$T{EAEf+y_0IO~81N&OMXh<8+(*?TODVsQKoXMF3!LBWVHl?00E_F3-Wmae1q^ zce>opocRf>Ef=$3fwz|c8glX{6+8jqo(Yw{?v28w9o(;vFa;PSM}kfh+8Pn=2HNg(e3kFT z%E`3wgfedim!C`Ai^#Udk8nx}e#P>x5+>d@E_krx*=4QXxz%irwK}w21A`-Ox`3_f z#Fm`4-M;xxy?>&Q~_SPm!6Kv=G2f+CWX!~T!2i>}Jh$cL5 zJA*@W2x>2Nd-eWwLlAs^3II6G>9Seg+_Xvcs=diSAA=%rc<5_8hXbQ=Q~V)#fhjkA!BVb6gk?@v-FYQr$=4mvdMpK=t>`1om&_ zUyp&mrvw0KS?t;VU$nh>Jk)I)2l^XCi_p`8>@||?B_a*wd8$cLTI@@yBo$*{hM7_+ zgvM6(3Z=3XvNOdHvLs7MWHbp`#yZwH*KhQ^Z_o3d^ZA@}KIi;b?)!J&_jO(0YrU7r zyhvNvf00ehUZGOXRF;>doNy`qm-NKoUIB6#9xF=dpFrijTve_>z7gh_3D#Q8XW z>5vPA6OtDlf}H|bTh^fi9FLxKG0BT&mjnv4XHFk)_!9jZd80wQny=H+EIiG7`*qsX z2*-zu(q{5m&Lit?hULTu*u{Zz4+l^+3>`qbqFwk-qhq}cb}eQ;=yEZ4+@5hDZnk{w zC8|mOIaPAD;c;=j25tWmucLDu1twbsxn5z)bjkY-_CB9v{1{|gXUo{EmS##R&;RxD z$=K1jvy7Lf!-A-?QyZe3j{Gztuy#56m1QiB@WnA}{nBID5G}mASj+b<$6BY%xAEKy zbO9fu(yfOF&OA2S;G0L%{TS(LBI{xtb9wMIY68qn=RDC!f;?m@ElQ^EprSo)FpaRzv~wbY~*G-#SB9`wZwjQMy{%KBN7j zt}Z&?rBjx}12d0Dz9>F^P&B||()SK^i)w)W|G|C$dh5Eum(kO9u8vf_(9TXkx%jn1 zpw~K=k$XHQ0cR$DVzKn}quPpk;?9#wG12z?j2@VG zj&6L6(W4PeuX#E(hxS2)Cy9m6%T5`vDE20+Q<362+pV6 zjhMkG&+#32>CWhRW#0L;9ML!z%Kg@i(QGO(fOdOc$=BRV{3NdId9sdgOtd0K*Cwxg zd7Rt47t?mqHjcndIW<>`F5gzNO>R+`&s74~@N}VznkK3z@}7=%@g^u$vr3<^CDC3@ z&k8zETFR%yZ;8D;IBqxDz4;@Sd-)^pnX^o{N!t%kKgb2|iJ_sg{n7o2ky-2T;8T8? zC2?VTrA7_%<^sR;q~!)wd6SLoE2=wHJl$VR@&yc*+h^mSC6%(IU}<6=rlEwQrdj)@ zCAs_bxR}J`&-)eH%6YH$%4nx!HH9+)mfn}(0|0ZanUa1^?G2cCRGwc;TZig_*>9p7> z?t}AT9X8kNEq+Gz#&0wai!R%SnqJinF~uF0b={31{POJ8&yvizm)n`)z7EIq#%mm% zM^s2QdpIh2sqwUBY)O3RdtR6Oo>gZ6z=WAJm-r97!KZ81qQ;;4y`ZsrYFo@7&lbxn zwg9QE%wAdm^wN?(+OYbg`yMZk_~r|RiB!^uX}N1b6%NZ^il`Qvn-Kv z07Yp>(y~hdpoz4ILt1SP-`eyKE;OQgXnO^?tyzjnZ>W*`6&NUBTJhzDoZ&@jXr?}w zsKT>civHZ}IsZv>*ktjrt-{}oyF428=1czKeNQt*bReAN@U{b)#%~HX`0@(v&oloL z`OxdlZ8>&F(pqTN6Kw0lZQ#2ZCa%Oj45Ai&Jtd+i@?~uA;}c43OC2V3LB0@@!iY4H zlXE%OhCu2s8NEaPT3zzT27AeJ($Jo~DzITM<0m76_MtXO_|k36^}DolF}2JiD}n>w zP?iXeSQ}Fu3~8N3ba z(c1#ik{Xs&^YcXS|^M&(E~7Em4(yHFAmNoD|l-K4$B)h5K(% zvdwhhw*V5in3ueLvhWGT{H5cT58n9U(&EOOLK=}b0;WG6CoR!q2Ry-<+gPP6+Vg)t zjhyDwIX(GdmeunTbz;=-g`FpD3ZE|TwfOnv7W)`GI9sWXFR^G_B9;CZexXqe`g|SW zm+}KEcS%LEyVM>z?MBE}sNUn=HrD9LrYC8lqns>kJW!rc6tBG*;@P#;VZws71S5%4 z%E62ktD(K%r3mhnoI>kml_bT)w#A>PE%>E>zNIINPqz>VWV1!HVqH{koaJMRV~x~Y zS|z!&m3W0bHnnxRbbjD>@k4e0>q8M-G~2g(R4s{kG#ajHeY{IMrZw!ag%*6DkyKoF z2IbVVIxCuNZk+>neM*NN<`o#MBb9G#LVaV+2Im4g_mr^iK_}#VkF)ze;~a%6mu$Rs zsHb2kQ5&atPlDO=v6Jlsy=XA=<3K$3EmuqfUw!`AgOBjHS2W~J11t8?Lx$aHHr}|Z^RW0t zEz`(+Jzolg`Qyoy7rN}UGlXv?Vagt0(vugxt`4b@vv&}h6smRmEph16JIDtVlhYH! z;}6U;7hfxj=zZj*BXvw8pA4@T-)^Iw(qxo988|7Q;{@gGsgGALZzpH#2S0L|k5Ins zM+z?v%+f_+OSXcWtyX!vgiU?Lacq@aDRh1JCv(+J2_%w}PlHyf6t3XpXYbbtvM9 zGNgu)sh;a{dwigGB}WW2Io?{r(ISsQIU|mDAuH{+wA#OaqiOv0Or1>ILEuaa$F_+_ z@(Syl6PM*riJ(lrNhnmf{M1XlRnji|GE6jp>aL4;WUK`)ZAt}Kg_1OAMtbW^uw^x+ zxyZYEfS@uZqI;8b@7A7sp_2~EK}CRZm)A*M%iPmt`x$0BL424j&X;=U6)v-ovs}yf zJp+F}$h{H&=(Gv6$7dbC7*|+@g~2VAaq$~R5)zW$YXGzrUo&WbcFA)-#tZaNh+~aJ(RA+arJlyHgF-C!~To z#0;ZBiI(J{N9*`-Hl+~$*j{M>H{T^`@F*82c${?j%`1>lA*<*d+G&Hz?8PuVtm#M1 zr_mmqRL5Tp<=Jq#Wp^!b>i^ird+lgBp^Qsj>Xvn^mOdczEcPSPaZuuDARU@}p4j(eJNU})R zy>gnLSBPRN9@+aaGLv%?flj^25@-9`G$!*3cX zT{uMBsn{E5kXOAO2DubFN4yZE<@pAk;w&KaPV?EIfF~Ti%vM4zuakZ%o)N#I_?5PQ zrqS0{5+;NeQJ7|_ZwbRJ$PRb9 zi%Bd#uUZ!_fbQFN<$7k}I==3XMzqZ@sAseC-Ak+{adQ%qyO@LC2o66~BC@p_@34Ur zp6Rhcp00H>=i#DTco61K*GmiO%k{xz>jetfK!BfBvJi3pc)VNYybkpT5ZSwSO{^pH z;m3u&FnpQ{?yIQW7jy(AWmlWIPv{-ngZ7ijk>@Sv`CI%opwC;Sn_;Y*>?MiP@j37K zbZXup`?LxA*)Go`&sz`=z2(G`X%&9B6!$^bjgv`h;j-;@H@bog!%M!t%!^qvU%0D; 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 literal 0 HcmV?d00001 From 9eb709baf388f39dabe7a89994dd188fcf7f88f5 Mon Sep 17 00:00:00 2001 From: Taylor Date: Mon, 14 Oct 2024 14:35:10 -0500 Subject: [PATCH 31/42] `chore: Add file type validation for uploaded case report template` --- backend/app/incidents/routes/db_operations.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/app/incidents/routes/db_operations.py b/backend/app/incidents/routes/db_operations.py index 3fa9ee53..8cab4fd4 100644 --- a/backend/app/incidents/routes/db_operations.py +++ b/backend/app/incidents/routes/db_operations.py @@ -4,6 +4,7 @@ from fastapi import APIRouter from fastapi import Depends +import mimetypes from fastapi import File from fastapi import HTTPException from fastapi import Query @@ -841,6 +842,11 @@ async def upload_case_report_template_endpoint( file: UploadFile = File(...), db: AsyncSession = Depends(get_db), ): + # Check if the file type is a .docx + mime_type, _ = mimetypes.guess_type(file.filename) + if mime_type != "application/vnd.openxmlformats-officedocument.wordprocessingml.document": + raise HTTPException(status_code=400, detail="Invalid file type. Only .docx files are allowed.") + if await report_template_exists(file.filename, db): raise HTTPException(status_code=400, detail="File name already exists for this template") return CaseReportTemplateDataStoreResponse( From 63a6bbc154fee4b545cc8e9e2e7c1c3fff25a772 Mon Sep 17 00:00:00 2001 From: Davide Di Modica Date: Tue, 15 Oct 2024 12:42:14 +0200 Subject: [PATCH 32/42] chore: update dependencies in frontend --- frontend/package-lock.json | 2337 ++++++++++++++++++++++++------------ frontend/package.json | 51 +- 2 files changed, 1579 insertions(+), 809 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 0629b3b0..0ad6d6ac 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,41 +10,38 @@ "dependencies": { "@ajoelp/json-to-formdata": "^1.5.0", "@f3ve/vue-markdown-it": "^0.2.2", - "@fontsource/jetbrains-mono": "^5.1.0", - "@fontsource/lexend": "^5.1.0", - "@fontsource/public-sans": "^5.1.0", - "@popperjs/core": "^2.11.8", - "@shikijs/markdown-it": "^1.21.0", - "@vueuse/components": "^11.1.0", + "@fontsource/jetbrains-mono": "^5.1.1", + "@fontsource/lexend": "^5.1.1", + "@fontsource/public-sans": "^5.1.1", + "@shikijs/markdown-it": "^1.22.0", "@vueuse/core": "^11.1.0", - "apexcharts": "^3.54.0", "axios": "^1.7.7", "bytes": "^3.1.2", "colord": "^2.9.3", - "crypto-js": "^4.2.0", "dayjs": "^1.11.13", "detect-touch-device": "^1.1.6", "echarts": "^5.5.1", "file-saver": "^2.0.5", "html-entities": "^2.5.2", - "jose": "^5.9.3", + "jose": "^5.9.4", "js-md5": "^0.8.3", "lodash": "^4.17.21", "mitt": "^3.0.1", "naive-ui": "^2.40.1", + "nanoid": "^5.0.7", "password-validator": "^5.3.0", "pinia": "^2.2.4", - "pinia-plugin-persistedstate": "^4.0.2", + "pinia-plugin-persistedstate": "^4.1.1", "secure-ls": "^2.0.0", - "shiki": "^1.21.0", + "shiki": "^1.22.0", "validator": "^13.12.0", - "vue": "^3.5.10", + "vue": "^3.5.12", "vue-advanced-cropper": "^2.8.9", "vue-highlight-words": "^3.0.1", - "vue-i18n": "^10.0.3", + "vue-i18n": "^10.0.4", "vue-router": "^4.4.5", "vue-sjv": "^0.0.6", - "vue3-apexcharts": "^1.6.0", + "vue3-apexcharts": "^1.7.0", "vue3-marquee": "^4.2.2", "vuedraggable": "^4.1.0" }, @@ -56,10 +53,9 @@ "@types/bytes": "^3.1.4", "@types/file-saver": "^2.0.7", "@types/fs-extra": "^11.0.4", - "@types/inquirer": "^9.0.7", "@types/jsdom": "^21.1.7", "@types/lodash": "^4.17.10", - "@types/node": "^22.7.4", + "@types/node": "^22.7.5", "@types/validator": "^13.12.2", "@vitejs/plugin-vue": "^5.1.4", "@vitejs/plugin-vue-jsx": "^4.0.1", @@ -67,30 +63,27 @@ "@vue/tsconfig": "^0.5.1", "autoprefixer": "^10.4.20", "cypress": "^13.15.0", - "eslint": "^9.11.1", + "depcheck": "^1.4.7", + "eslint": "^9.12.0", "flourite": "^1.3.0", "fs-extra": "^11.2.0", - "globals": "^15.10.0", "jsdom": "^25.0.1", - "json5": "^2.2.3", "npm-run-all2": "^6.2.3", - "picocolors": "^1.1.0", "postcss": "^8.4.47", "prettier": "^3.3.3", - "sass": "^1.79.4", + "sass": "^1.79.5", "start-server-and-test": "^2.0.8", "tailwind-config-viewer": "^2.0.4", "tailwindcss": "^3.4.13", "taze": "^0.17.2", "type-fest": "^4.26.1", - "typescript": "^5.5.4", + "typescript": "~5.5.4", "unplugin-vue-components": "^0.27.4", - "vite": "^5.4.8", - "vite-bundle-analyzer": "^0.12.1", + "vite": "^5.4.9", "vite-bundle-visualizer": "^1.2.1", "vite-plugin-vue-devtools": "^7.4.6", "vite-svg-loader": "^5.1.0", - "vitest": "^2.1.2", + "vitest": "^2.1.3", "vue-tsc": "^2.1.6" }, "engines": { @@ -275,11 +268,11 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/highlight": "^7.25.7", "picocolors": "^1.0.0" }, "engines": { @@ -287,28 +280,28 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", - "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.8.tgz", + "integrity": "sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.8.tgz", + "integrity": "sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helpers": "^7.25.7", + "@babel/parser": "^7.25.8", + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.8", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -332,39 +325,39 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", - "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", + "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", "dependencies": { - "@babel/types": "^7.25.6", + "@babel/types": "^7.25.7", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", + "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", + "@babel/compat-data": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -381,17 +374,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", - "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz", + "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.25.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/traverse": "^7.25.4", + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/traverse": "^7.25.7", "semver": "^6.3.1" }, "engines": { @@ -411,39 +404,39 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", - "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz", + "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==", "dev": true, "dependencies": { - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.8" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", + "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", + "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -453,35 +446,35 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", - "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz", + "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==", "dev": true, "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", + "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", - "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz", + "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==", "dev": true, "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/traverse": "^7.25.0" + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -491,72 +484,72 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", + "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", - "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz", + "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==", "dev": true, "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", + "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", - "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", + "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6" + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -566,11 +559,11 @@ } }, "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", + "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", "dependencies": { - "@babel/types": "^7.25.6" + "@babel/types": "^7.25.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -580,14 +573,14 @@ } }, "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.7.tgz", - "integrity": "sha512-RL9GR0pUG5Kc8BUWLNDm2T5OpYwSX15r98I0IkgmRQTXuELq/OynH8xtMTMvTJFjXbMWFVTKtYkTaYQsuAwQlQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.7.tgz", + "integrity": "sha512-q1mqqqH0e1lhmsEQHV5U8OmdueBC2y0RFr2oUzZoFRtN3MvPmt2fsFRcNQAoGLTSNdHBFUYGnlgcRFhkBbKjPw==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-decorators": "^7.24.7" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/plugin-syntax-decorators": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -597,12 +590,12 @@ } }, "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.7.tgz", - "integrity": "sha512-Ui4uLJJrRV1lb38zg1yYTmRKmiZLiftDEvZN2iq3kd9kUFU+PttmzTbAFC2ucRk/XJmtek6G23gPsuZbhrT8fQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.7.tgz", + "integrity": "sha512-oXduHo642ZhstLVYTe2z2GSJIruU0c/W3/Ghr6A5yGMsVrvdnxO1z+3pbTcT7f3/Clnt+1z8D/w1r1f1SHaCHw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -612,12 +605,12 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", - "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.7.tgz", + "integrity": "sha512-AqVo+dguCgmpi/3mYBdu9lkngOBlQ2w2vnNpa6gfiCxQZLzV4ZbhsXitJ2Yblkoe1VQwtHSaNmIaGll/26YWRw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -639,12 +632,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.7.tgz", + "integrity": "sha512-ruZOnKO+ajVL/MVx+PwNBPOkrnXTXoWMtte1MBpegfCArhqOe3Bj52avVj1huLLxNKYKXYaSxZ2F+woK1ekXfw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -654,12 +647,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", - "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.7.tgz", + "integrity": "sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -669,16 +662,16 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", - "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.7.tgz", + "integrity": "sha512-VKlgy2vBzj8AmEzunocMun2fF06bsSWV+FvVXohtL6FGve/+L217qhHxRTVGHEDO/YR8IANcjzgJsd04J8ge5Q==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.25.0", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-syntax-typescript": "^7.24.7" + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-syntax-typescript": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -688,36 +681,36 @@ } }, "node_modules/@babel/standalone": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.25.6.tgz", - "integrity": "sha512-Kf2ZcZVqsKbtYhlA7sP0z5A3q5hmCVYMKMWRWNK/5OVwHIve3JY1djVRmIVAx8FMueLIfZGKQDIILK2w8zO4mg==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.25.8.tgz", + "integrity": "sha512-UvRanvLCGPRscJ5Rw9o6vUBS5P+E+gkhl6eaokrIN+WM1kUkmj254VZhyihFdDZVDlI3cPcZoakbJJw24QPISw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", + "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/code-frame": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", - "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.6", - "@babel/parser": "^7.25.6", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", + "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", + "dependencies": { + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -734,12 +727,12 @@ } }, "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", + "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -773,6 +766,7 @@ }, "node_modules/@clack/prompts/node_modules/is-unicode-supported": { "version": "1.3.0", + "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -1312,12 +1306,20 @@ } }, "node_modules/@eslint/compat": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz", - "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.0.tgz", + "integrity": "sha512-CkPWddN7J9JPrQedEr2X7AjK9y1jaMJtxZ4A/+jTMFA2+n5BWhcKHW/EbJyARqg2zzQfgtWUtVmG3hrG6+nGpg==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^9.10.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, "node_modules/@eslint/config-array": { @@ -1383,6 +1385,11 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1403,6 +1410,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1423,9 +1441,9 @@ } }, "node_modules/@eslint/markdown": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.1.1.tgz", - "integrity": "sha512-Z+1js5AeqidwhNBbnIPM6Fn4eY9D5i1NleamS0UBW6BG0J4lpvhIVOKVIi22kmH5gvxDmHUp5MHkkkjda0TehA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.2.0.tgz", + "integrity": "sha512-ZLWZ6RNy5flf1Nk2DBt0V77MQpQEo8snkjVT75P5J0SJkE/QNoqgy7+dBvNjlyZuj664pU43uDXWg3J8AfF0IQ==", "dev": true, "dependencies": { "@eslint/plugin-kit": "^0.2.0", @@ -1758,19 +1776,19 @@ } }, "node_modules/@fontsource/jetbrains-mono": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@fontsource/jetbrains-mono/-/jetbrains-mono-5.1.0.tgz", - "integrity": "sha512-YzWpGYY3PoqvmvwW2Hb4NwkN5C7LO0FmZugEGcFe6cNNE/cMgH9JhW5LI6hjG+1+nwgSHyJtKmblHNrUqlyhWg==" + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@fontsource/jetbrains-mono/-/jetbrains-mono-5.1.1.tgz", + "integrity": "sha512-5rwvmdQQpXev4LlBX1P+7h2dguu6iwW/9Npjde4+DEq+HgpVJI/7QY8DI1NVVFdvLtXZNP+vO2L/5BQED6FUhA==" }, "node_modules/@fontsource/lexend": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@fontsource/lexend/-/lexend-5.1.0.tgz", - "integrity": "sha512-mqwRfsRobLoj4iHqkvMGMMiTYU7n0hbgGftGBKFGKGyedseQOQ3k7iCBVTAU9wIyfq02Rypd9BrLXChHwFvg0Q==" + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@fontsource/lexend/-/lexend-5.1.1.tgz", + "integrity": "sha512-92A96vmx5xk1NgNphB62w5PKhW53Ruo74ki3UsUrV1q7/tbhJ73k2podhCNmldUlpUeO6rrCUWpRM20WloiNXA==" }, "node_modules/@fontsource/public-sans": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@fontsource/public-sans/-/public-sans-5.1.0.tgz", - "integrity": "sha512-94+468XL9dUxsZ5edw/AtBHLdIwkvqr3WBUMBD30LUQzJpHw/Fxd7VrgkXSIKRIwYi3pTuQ1Q2Vj3COGIwi58Q==" + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@fontsource/public-sans/-/public-sans-5.1.1.tgz", + "integrity": "sha512-BEJEc9kpLBowHLqeOlex1lMJPZ/6mzKn3ArhbvWY9dvMcjSqH7jzJyTN44j0H78FTOrVjIW1g4A8nDdbx8VV5Q==" }, "node_modules/@hapi/hoek": { "version": "9.3.0", @@ -1787,6 +1805,26 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@humanfs/core": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", + "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", + "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "dependencies": { + "@humanfs/core": "^0.19.0", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", @@ -1844,9 +1882,9 @@ "peer": true }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "engines": { "node": ">=18.18" }, @@ -1877,12 +1915,12 @@ } }, "node_modules/@intlify/core-base": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-10.0.3.tgz", - "integrity": "sha512-ysJnTGDtuXPa6R2Ii4JIvfMVvDahUUny3aY8+P4r6/0TYHkblgzIMjV6cAn60em67AB0M7OWNAdcAVfWWeN8Qg==", + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-10.0.4.tgz", + "integrity": "sha512-GG428DkrrWCMhxRMRQZjuS7zmSUzarYcaHJqG9VB8dXAxw4iQDoKVQ7ChJRB6ZtsCsX3Jse1PEUlHrJiyQrOTg==", "dependencies": { - "@intlify/message-compiler": "10.0.3", - "@intlify/shared": "10.0.3" + "@intlify/message-compiler": "10.0.4", + "@intlify/shared": "10.0.4" }, "engines": { "node": ">= 16" @@ -1892,11 +1930,11 @@ } }, "node_modules/@intlify/message-compiler": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-10.0.3.tgz", - "integrity": "sha512-KC2fG8nCzSYmXjHptEt6i/xM3k6S2szsPaHDCRgWKEYAbeHe6JFm6X4KRw3Csy112A8CxpavMi1dh3h7khwV5w==", + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-10.0.4.tgz", + "integrity": "sha512-AFbhEo10DP095/45EauinQJ5hJ3rJUmuuqltGguvc3WsvezZN+g8qNHLGWKu60FHQVizMrQY7VJ+zVlBXlQQkQ==", "dependencies": { - "@intlify/shared": "10.0.3", + "@intlify/shared": "10.0.4", "source-map-js": "^1.0.2" }, "engines": { @@ -1907,9 +1945,9 @@ } }, "node_modules/@intlify/shared": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-10.0.3.tgz", - "integrity": "sha512-PWxrCb6fDlnoGLnXLlWu6d7o/HdWACB9TjRnpLro+9uyfqgWA9hvqg5vekcPRyraTieV5srCbTk/ldYw9V3LHw==", + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-10.0.4.tgz", + "integrity": "sha512-ukFn0I01HsSgr3VYhYcvkTCLS7rGa0gw4A4AMpcy/A9xx/zRJy7PS2BElMXLwUazVFMAr5zuiTk3MQeoeGXaJg==", "engines": { "node": ">= 16" }, @@ -2138,6 +2176,279 @@ "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", "dev": true }, + "node_modules/@parcel/watcher": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz", + "integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.4.1", + "@parcel/watcher-darwin-arm64": "2.4.1", + "@parcel/watcher-darwin-x64": "2.4.1", + "@parcel/watcher-freebsd-x64": "2.4.1", + "@parcel/watcher-linux-arm-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-musl": "2.4.1", + "@parcel/watcher-linux-x64-glibc": "2.4.1", + "@parcel/watcher-linux-x64-musl": "2.4.1", + "@parcel/watcher-win32-arm64": "2.4.1", + "@parcel/watcher-win32-ia32": "2.4.1", + "@parcel/watcher-win32-x64": "2.4.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz", + "integrity": "sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz", + "integrity": "sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz", + "integrity": "sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz", + "integrity": "sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz", + "integrity": "sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz", + "integrity": "sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz", + "integrity": "sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz", + "integrity": "sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz", + "integrity": "sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz", + "integrity": "sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz", + "integrity": "sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz", + "integrity": "sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -2165,15 +2476,6 @@ "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", "dev": true }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, "node_modules/@rollup/pluginutils": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz", @@ -2207,9 +2509,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.5.tgz", - "integrity": "sha512-SU5cvamg0Eyu/F+kLeMXS7GoahL+OoizlclVFX3l5Ql6yNlywJJ0OuqTzUx0v+aHhPHEB/56CT06GQrRrGNYww==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", "cpu": [ "arm" ], @@ -2220,9 +2522,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.5.tgz", - "integrity": "sha512-S4pit5BP6E5R5C8S6tgU/drvgjtYW76FBuG6+ibG3tMvlD1h9LHVF9KmlmaUBQ8Obou7hEyS+0w+IR/VtxwNMQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", "cpu": [ "arm64" ], @@ -2233,9 +2535,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.5.tgz", - "integrity": "sha512-250ZGg4ipTL0TGvLlfACkIxS9+KLtIbn7BCZjsZj88zSg2Lvu3Xdw6dhAhfe/FjjXPVNCtcSp+WZjVsD3a/Zlw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", "cpu": [ "arm64" ], @@ -2246,9 +2548,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.5.tgz", - "integrity": "sha512-D8brJEFg5D+QxFcW6jYANu+Rr9SlKtTenmsX5hOSzNYVrK5oLAEMTUgKWYJP+wdKyCdeSwnapLsn+OVRFycuQg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", "cpu": [ "x64" ], @@ -2259,9 +2561,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.5.tgz", - "integrity": "sha512-PNqXYmdNFyWNg0ma5LdY8wP+eQfdvyaBAojAXgO7/gs0Q/6TQJVXAXe8gwW9URjbS0YAammur0fynYGiWsKlXw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", "cpu": [ "arm" ], @@ -2272,9 +2574,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.5.tgz", - "integrity": "sha512-kSSCZOKz3HqlrEuwKd9TYv7vxPYD77vHSUvM2y0YaTGnFc8AdI5TTQRrM1yIp3tXCKrSL9A7JLoILjtad5t8pQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", "cpu": [ "arm" ], @@ -2285,9 +2587,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.5.tgz", - "integrity": "sha512-oTXQeJHRbOnwRnRffb6bmqmUugz0glXaPyspp4gbQOPVApdpRrY/j7KP3lr7M8kTfQTyrBUzFjj5EuHAhqH4/w==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", "cpu": [ "arm64" ], @@ -2298,9 +2600,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.5.tgz", - "integrity": "sha512-qnOTIIs6tIGFKCHdhYitgC2XQ2X25InIbZFor5wh+mALH84qnFHvc+vmWUpyX97B0hNvwNUL4B+MB8vJvH65Fw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", "cpu": [ "arm64" ], @@ -2311,9 +2613,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.5.tgz", - "integrity": "sha512-TMYu+DUdNlgBXING13rHSfUc3Ky5nLPbWs4bFnT+R6Vu3OvXkTkixvvBKk8uO4MT5Ab6lC3U7x8S8El2q5o56w==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", "cpu": [ "ppc64" ], @@ -2324,9 +2626,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.5.tgz", - "integrity": "sha512-PTQq1Kz22ZRvuhr3uURH+U/Q/a0pbxJoICGSprNLAoBEkyD3Sh9qP5I0Asn0y0wejXQBbsVMRZRxlbGFD9OK4A==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", "cpu": [ "riscv64" ], @@ -2337,9 +2639,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.5.tgz", - "integrity": "sha512-bR5nCojtpuMss6TDEmf/jnBnzlo+6n1UhgwqUvRoe4VIotC7FG1IKkyJbwsT7JDsF2jxR+NTnuOwiGv0hLyDoQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", "cpu": [ "s390x" ], @@ -2362,9 +2664,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.5.tgz", - "integrity": "sha512-uBa2e28ohzNNwjr6Uxm4XyaA1M/8aTgfF2T7UIlElLaeXkgpmIJ2EitVNQxjO9xLLLy60YqAgKn/AqSpCUkE9g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", "cpu": [ "x64" ], @@ -2375,9 +2677,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.5.tgz", - "integrity": "sha512-RXT8S1HP8AFN/Kr3tg4fuYrNxZ/pZf1HemC5Tsddc6HzgGnJm0+Lh5rAHJkDuW3StI0ynNXukidROMXYl6ew8w==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", "cpu": [ "arm64" ], @@ -2388,9 +2690,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.5.tgz", - "integrity": "sha512-ElTYOh50InL8kzyUD6XsnPit7jYCKrphmddKAe1/Ytt74apOxDq5YEcbsiKs0fR3vff3jEneMM+3I7jbqaMyBg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", "cpu": [ "ia32" ], @@ -2401,9 +2703,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.5.tgz", - "integrity": "sha512-+lvL/4mQxSV8MukpkKyyvfwhH266COcWlXE/1qxwN08ajovta3459zrjLghYMgDerlzNwLAcFpvU+WWE5y6nAQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", "cpu": [ "x64" ], @@ -2414,59 +2716,59 @@ ] }, "node_modules/@shikijs/core": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.21.0.tgz", - "integrity": "sha512-zAPMJdiGuqXpZQ+pWNezQAk5xhzRXBNiECFPcJLtUdsFM3f//G95Z15EHTnHchYycU8kIIysqGgxp8OVSj1SPQ==", - "dependencies": { - "@shikijs/engine-javascript": "1.21.0", - "@shikijs/engine-oniguruma": "1.21.0", - "@shikijs/types": "1.21.0", - "@shikijs/vscode-textmate": "^9.2.2", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", + "integrity": "sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==", + "dependencies": { + "@shikijs/engine-javascript": "1.22.0", + "@shikijs/engine-oniguruma": "1.22.0", + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.3" } }, "node_modules/@shikijs/engine-javascript": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.21.0.tgz", - "integrity": "sha512-jxQHNtVP17edFW4/0vICqAVLDAxmyV31MQJL4U/Kg+heQALeKYVOWo0sMmEZ18FqBt+9UCdyqGKYE7bLRtk9mg==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.0.tgz", + "integrity": "sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==", "dependencies": { - "@shikijs/types": "1.21.0", - "@shikijs/vscode-textmate": "^9.2.2", + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", "oniguruma-to-js": "0.4.3" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.21.0.tgz", - "integrity": "sha512-AIZ76XocENCrtYzVU7S4GY/HL+tgHGbVU+qhiDyNw1qgCA5OSi4B4+HY4BtAoJSMGuD/L5hfTzoRVbzEm2WTvg==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.0.tgz", + "integrity": "sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==", "dependencies": { - "@shikijs/types": "1.21.0", - "@shikijs/vscode-textmate": "^9.2.2" + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0" } }, "node_modules/@shikijs/markdown-it": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@shikijs/markdown-it/-/markdown-it-1.21.0.tgz", - "integrity": "sha512-wNvze11LNnhNc3NpGG7Y2Jxlecta85bd1QRltB+oqtug4w63BtjzTQubpB3NWwXTWXf91iVlmbo8Sp9mrmZVGQ==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/markdown-it/-/markdown-it-1.22.0.tgz", + "integrity": "sha512-IAWi2pbzYndiuXOWnV5Ll4ULQJeWl45WUACl1Xc2KSiBl0JtQmqKvPOGKN7YSZbyIzkB6bWUItRrv5ucO35U+g==", "dependencies": { "markdown-it": "^14.1.0", - "shiki": "1.21.0" + "shiki": "1.22.0" } }, "node_modules/@shikijs/types": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.21.0.tgz", - "integrity": "sha512-tzndANDhi5DUndBtpojEq/42+dpUF2wS7wdCDQaFtIXm3Rd1QkrcVgSSRLOvEwexekihOXfbYJINW37g96tJRw==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.0.tgz", + "integrity": "sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==", "dependencies": { - "@shikijs/vscode-textmate": "^9.2.2", + "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4" } }, "node_modules/@shikijs/vscode-textmate": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.2.2.tgz", - "integrity": "sha512-TMp15K+GGYrWlZM8+Lnj9EaHEFmOen0WJBrfa17hF7taDOYthuPPV0GWzfd/9iMij0akS/8Yw2ikquH7uVi/fg==" + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz", + "integrity": "sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==" }, "node_modules/@sideway/address": { "version": "4.1.5", @@ -2501,14 +2803,14 @@ } }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.8.0.tgz", - "integrity": "sha512-Ufvk7hP+bf+pD35R/QfunF793XlSRIC7USr3/EdgduK9j13i2JjmsM0LUz3/foS+jDYp2fzyWZA9N44CPur0Ow==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.9.0.tgz", + "integrity": "sha512-OrDyFAYjBT61122MIY1a3SfEgy3YCMgt2vL4eoPmvTwDBwyQhAXurxNQznlRD/jESNfYWfID8Ej+31LljvF7Xg==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "^8.4.0", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", + "@typescript-eslint/utils": "^8.8.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, @@ -2578,16 +2880,6 @@ "@types/unist": "*" } }, - "node_modules/@types/inquirer": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.7.tgz", - "integrity": "sha512-Q0zyBupO6NxGRZut/JdmqYKOnN95Eg5V8Csg3PGKkP+FnvsUZx1jAyK7fztIszxxMuoBA6E3KXWvdZVXIpx60g==", - "dev": true, - "dependencies": { - "@types/through": "*", - "rxjs": "^7.2.0" - } - }, "node_modules/@types/jsdom": { "version": "21.1.7", "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", @@ -2639,6 +2931,12 @@ "@types/unist": "*" } }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, "node_modules/@types/ms": { "version": "0.7.34", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", @@ -2646,9 +2944,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.7.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", - "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", "dev": true, "dependencies": { "undici-types": "~6.19.2" @@ -2660,6 +2958,12 @@ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "dev": true + }, "node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", @@ -2677,15 +2981,6 @@ "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", "dev": true }, - "node_modules/@types/through": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz", - "integrity": "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/tough-cookie": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", @@ -2719,16 +3014,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz", - "integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.9.0.tgz", + "integrity": "sha512-Y1n621OCy4m7/vTXNlCbMVp87zSd7NH0L9cXD8aIpOaNlzeWxIK4+Q19A68gSmTNRZn92UjocVUWDthGxtqHFg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/type-utils": "8.7.0", - "@typescript-eslint/utils": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.9.0", + "@typescript-eslint/type-utils": "8.9.0", + "@typescript-eslint/utils": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -2752,15 +3047,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.7.0.tgz", - "integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.9.0.tgz", + "integrity": "sha512-U+BLn2rqTTHnc4FL3FJjxaXptTxmf9sNftJK62XLz4+GxG3hLHm/SUNaaXP5Y4uTiuYoL5YLy4JBCJe3+t8awQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.9.0", + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/typescript-estree": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0", "debug": "^4.3.4" }, "engines": { @@ -2780,13 +3075,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz", - "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.9.0.tgz", + "integrity": "sha512-bZu9bUud9ym1cabmOYH9S6TnbWRzpklVmwqICeOulTCZ9ue2/pczWzQvt/cGj2r2o1RdKoZbuEMalJJSYw3pHQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0" + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2797,13 +3092,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz", - "integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.9.0.tgz", + "integrity": "sha512-JD+/pCqlKqAk5961vxCluK+clkppHY07IbV3vett97KOV+8C6l+CPEPwpUuiMwgbOz/qrN3Ke4zzjqbT+ls+1Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/utils": "8.7.0", + "@typescript-eslint/typescript-estree": "8.9.0", + "@typescript-eslint/utils": "8.9.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2821,9 +3116,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz", - "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.9.0.tgz", + "integrity": "sha512-SjgkvdYyt1FAPhU9c6FiYCXrldwYYlIQLkuc+LfAhCna6ggp96ACncdtlbn8FmnG72tUkXclrDExOpEYf1nfJQ==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2834,13 +3129,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz", - "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.9.0.tgz", + "integrity": "sha512-9iJYTgKLDG6+iqegehc5+EqE6sqaee7kb8vWpmHZ86EqwDjmlqNNHeqDVqb9duh+BY6WCNHfIGvuVU3Tf9Db0g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/visitor-keys": "8.9.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2862,15 +3157,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz", - "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.9.0.tgz", + "integrity": "sha512-PKgMmaSo/Yg/F7kIZvrgrWa1+Vwn036CdNUvYFEkYbPwOH4i8xvkaRlu148W3vtheWK9ckKRIz7PBP5oUlkrvQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0" + "@typescript-eslint/scope-manager": "8.9.0", + "@typescript-eslint/types": "8.9.0", + "@typescript-eslint/typescript-estree": "8.9.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2884,12 +3179,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz", - "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.9.0.tgz", + "integrity": "sha512-Ht4y38ubk4L5/U8xKUBfKNYGmvKvA1CANoxiTRMM+tOLk3lbF3DvzZCxJCRSE+2GdCMSh6zq9VZJc3asc1XuAA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/types": "8.9.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -3127,6 +3422,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/@unocss/eslint-plugin/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "peer": true + }, "node_modules/@unocss/eslint-plugin/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3165,6 +3466,7 @@ "version": "8.57.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -3351,6 +3653,18 @@ "node": ">=8" } }, + "node_modules/@unocss/eslint-plugin/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "peer": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/@unocss/eslint-plugin/node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -3429,9 +3743,9 @@ } }, "node_modules/@vitest/eslint-plugin": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.1.4.tgz", - "integrity": "sha512-kudjgefmJJ7xQ2WfbUU6pZbm7Ou4gLYRaao/8Ynide3G0QhVKHd978sDyWX4KOH0CCMH9cyrGAkFd55eGzJ48Q==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.1.7.tgz", + "integrity": "sha512-pTWGW3y6lH2ukCuuffpan6kFxG6nIuoesbhMiQxskyQMRcCN5t9SXsKrNHvEw3p8wcCsgJoRqFZVkOTn6TjclA==", "dev": true, "peerDependencies": { "@typescript-eslint/utils": ">= 8.0", @@ -3440,9 +3754,6 @@ "vitest": "*" }, "peerDependenciesMeta": { - "@typescript-eslint/utils": { - "optional": true - }, "typescript": { "optional": true }, @@ -3452,13 +3763,13 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.2.tgz", - "integrity": "sha512-FEgtlN8mIUSEAAnlvn7mP8vzaWhEaAEvhSXCqrsijM7K6QqjB11qoRZYEd4AKSCDz8p0/+yH5LzhZ47qt+EyPg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz", + "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==", "dev": true, "dependencies": { - "@vitest/spy": "2.1.2", - "@vitest/utils": "2.1.2", + "@vitest/spy": "2.1.3", + "@vitest/utils": "2.1.3", "chai": "^5.1.1", "tinyrainbow": "^1.2.0" }, @@ -3467,12 +3778,12 @@ } }, "node_modules/@vitest/mocker": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.2.tgz", - "integrity": "sha512-ExElkCGMS13JAJy+812fw1aCv2QO/LBK6CyO4WOPAzLTmve50gydOlWhgdBJPx2ztbADUq3JVI0C5U+bShaeEA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz", + "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==", "dev": true, "dependencies": { - "@vitest/spy": "^2.1.0-beta.1", + "@vitest/spy": "2.1.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.11" }, @@ -3480,7 +3791,7 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/spy": "2.1.2", + "@vitest/spy": "2.1.3", "msw": "^2.3.5", "vite": "^5.0.0" }, @@ -3503,9 +3814,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.2.tgz", - "integrity": "sha512-FIoglbHrSUlOJPDGIrh2bjX1sNars5HbxlcsFKCtKzu4+5lpsRhOCVcuzp0fEhAGHkPZRIXVNzPcpSlkoZ3LuA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz", + "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==", "dev": true, "dependencies": { "tinyrainbow": "^1.2.0" @@ -3515,12 +3826,12 @@ } }, "node_modules/@vitest/runner": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.2.tgz", - "integrity": "sha512-UCsPtvluHO3u7jdoONGjOSil+uON5SSvU9buQh3lP7GgUXHp78guN1wRmZDX4wGK6J10f9NUtP6pO+SFquoMlw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz", + "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==", "dev": true, "dependencies": { - "@vitest/utils": "2.1.2", + "@vitest/utils": "2.1.3", "pathe": "^1.1.2" }, "funding": { @@ -3528,12 +3839,12 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.2.tgz", - "integrity": "sha512-xtAeNsZ++aRIYIUsek7VHzry/9AcxeULlegBvsdLncLmNCR6tR8SRjn8BbDP4naxtccvzTqZ+L1ltZlRCfBZFA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz", + "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==", "dev": true, "dependencies": { - "@vitest/pretty-format": "2.1.2", + "@vitest/pretty-format": "2.1.3", "magic-string": "^0.30.11", "pathe": "^1.1.2" }, @@ -3542,9 +3853,9 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.2.tgz", - "integrity": "sha512-GSUi5zoy+abNRJwmFhBDC0yRuVUn8WMlQscvnbbXdKLXX9dE59YbfwXxuJ/mth6eeqIzofU8BB5XDo/Ns/qK2A==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz", + "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==", "dev": true, "dependencies": { "tinyspy": "^3.0.0" @@ -3554,12 +3865,12 @@ } }, "node_modules/@vitest/utils": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.2.tgz", - "integrity": "sha512-zMO2KdYy6mx56btx9JvAqAZ6EyS3g49krMPPrgOp1yxGZiA93HumGk+bZ5jIZtOg5/VBYl5eBmGRQHqq4FG6uQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz", + "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==", "dev": true, "dependencies": { - "@vitest/pretty-format": "2.1.2", + "@vitest/pretty-format": "2.1.3", "loupe": "^3.1.1", "tinyrainbow": "^1.2.0" }, @@ -3568,27 +3879,27 @@ } }, "node_modules/@volar/language-core": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.5.tgz", - "integrity": "sha512-F4tA0DCO5Q1F5mScHmca0umsi2ufKULAnMOVBfMsZdT4myhVl4WdKRwCaKcfOkIEuyrAVvtq1ESBdZ+rSyLVww==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.6.tgz", + "integrity": "sha512-FxUfxaB8sCqvY46YjyAAV6c3mMIq/NWQMVvJ+uS4yxr1KzOvyg61gAuOnNvgCvO4TZ7HcLExBEsWcDu4+K4E8A==", "dev": true, "dependencies": { - "@volar/source-map": "2.4.5" + "@volar/source-map": "2.4.6" } }, "node_modules/@volar/source-map": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.5.tgz", - "integrity": "sha512-varwD7RaKE2J/Z+Zu6j3mNNJbNT394qIxXwdvz/4ao/vxOfyClZpSDtLKkwWmecinkOVos5+PWkWraelfMLfpw==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.6.tgz", + "integrity": "sha512-Nsh7UW2ruK+uURIPzjJgF0YRGP5CX9nQHypA2OMqdM2FKy7rh+uv3XgPnWPw30JADbKvZ5HuBzG4gSbVDYVtiw==", "dev": true }, "node_modules/@volar/typescript": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.5.tgz", - "integrity": "sha512-mcT1mHvLljAEtHviVcBuOyAwwMKz1ibXTi5uYtP/pf4XxoAzpdkQ+Br2IC0NPCvLCbjPZmbf3I0udndkfB1CDg==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.6.tgz", + "integrity": "sha512-NMIrA7y5OOqddL9VtngPWYmdQU03htNKFtAYidbYfWA0TOhyGVd9tfcP4TsLWQ+RBWDZCbBqsr8xzU0ZOxYTCQ==", "dev": true, "dependencies": { - "@volar/language-core": "2.4.5", + "@volar/language-core": "2.4.6", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } @@ -3642,36 +3953,36 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.10.tgz", - "integrity": "sha512-iXWlk+Cg/ag7gLvY0SfVucU8Kh2CjysYZjhhP70w9qI4MvSox4frrP+vDGvtQuzIcgD8+sxM6lZvCtdxGunTAA==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.12.tgz", + "integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==", "dependencies": { "@babel/parser": "^7.25.3", - "@vue/shared": "3.5.10", + "@vue/shared": "3.5.12", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.10.tgz", - "integrity": "sha512-DyxHC6qPcktwYGKOIy3XqnHRrrXyWR2u91AjP+nLkADko380srsC2DC3s7Y1Rk6YfOlxOlvEQKa9XXmLI+W4ZA==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.12.tgz", + "integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==", "dependencies": { - "@vue/compiler-core": "3.5.10", - "@vue/shared": "3.5.10" + "@vue/compiler-core": "3.5.12", + "@vue/shared": "3.5.12" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.10.tgz", - "integrity": "sha512-to8E1BgpakV7224ZCm8gz1ZRSyjNCAWEplwFMWKlzCdP9DkMKhRRwt0WkCjY7jkzi/Vz3xgbpeig5Pnbly4Tow==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.12.tgz", + "integrity": "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==", "dependencies": { "@babel/parser": "^7.25.3", - "@vue/compiler-core": "3.5.10", - "@vue/compiler-dom": "3.5.10", - "@vue/compiler-ssr": "3.5.10", - "@vue/shared": "3.5.10", + "@vue/compiler-core": "3.5.12", + "@vue/compiler-dom": "3.5.12", + "@vue/compiler-ssr": "3.5.12", + "@vue/shared": "3.5.12", "estree-walker": "^2.0.2", "magic-string": "^0.30.11", "postcss": "^8.4.47", @@ -3679,12 +3990,12 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.10.tgz", - "integrity": "sha512-hxP4Y3KImqdtyUKXDRSxKSRkSm1H9fCvhojEYrnaoWhE4w/y8vwWhnosJoPPe2AXm5sU7CSbYYAgkt2ZPhDz+A==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.12.tgz", + "integrity": "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==", "dependencies": { - "@vue/compiler-dom": "3.5.10", - "@vue/shared": "3.5.10" + "@vue/compiler-dom": "3.5.12", + "@vue/shared": "3.5.12" } }, "node_modules/@vue/compiler-vue2": { @@ -3719,6 +4030,24 @@ "vue": "^3.0.0" } }, + "node_modules/@vue/devtools-core/node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/@vue/devtools-kit": { "version": "7.4.6", "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.4.6.tgz", @@ -3768,49 +4097,49 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.10.tgz", - "integrity": "sha512-kW08v06F6xPSHhid9DJ9YjOGmwNDOsJJQk0ax21wKaUYzzuJGEuoKNU2Ujux8FLMrP7CFJJKsHhXN9l2WOVi2g==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.12.tgz", + "integrity": "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==", "dependencies": { - "@vue/shared": "3.5.10" + "@vue/shared": "3.5.12" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.10.tgz", - "integrity": "sha512-9Q86I5Qq3swSkFfzrZ+iqEy7Vla325M7S7xc1NwKnRm/qoi1Dauz0rT6mTMmscqx4qz0EDJ1wjB+A36k7rl8mA==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.12.tgz", + "integrity": "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==", "dependencies": { - "@vue/reactivity": "3.5.10", - "@vue/shared": "3.5.10" + "@vue/reactivity": "3.5.12", + "@vue/shared": "3.5.12" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.10.tgz", - "integrity": "sha512-t3x7ht5qF8ZRi1H4fZqFzyY2j+GTMTDxRheT+i8M9Ph0oepUxoadmbwlFwMoW7RYCpNQLpP2Yx3feKs+fyBdpA==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.12.tgz", + "integrity": "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==", "dependencies": { - "@vue/reactivity": "3.5.10", - "@vue/runtime-core": "3.5.10", - "@vue/shared": "3.5.10", + "@vue/reactivity": "3.5.12", + "@vue/runtime-core": "3.5.12", + "@vue/shared": "3.5.12", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.10.tgz", - "integrity": "sha512-IVE97tt2kGKwHNq9yVO0xdh1IvYfZCShvDSy46JIh5OQxP1/EXSpoDqetVmyIzL7CYOWnnmMkVqd7YK2QSWkdw==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.12.tgz", + "integrity": "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==", "dependencies": { - "@vue/compiler-ssr": "3.5.10", - "@vue/shared": "3.5.10" + "@vue/compiler-ssr": "3.5.12", + "@vue/shared": "3.5.12" }, "peerDependencies": { - "vue": "3.5.10" + "vue": "3.5.12" } }, "node_modules/@vue/shared": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.10.tgz", - "integrity": "sha512-VkkBhU97Ki+XJ0xvl4C9YJsIZ2uIlQ7HqPpZOS3m9VCvmROPaChZU6DexdMJqvz9tbgG+4EtFVrSuailUq5KGQ==" + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.12.tgz", + "integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==" }, "node_modules/@vue/test-utils": { "version": "2.4.6", @@ -3828,41 +4157,6 @@ "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==", "dev": true }, - "node_modules/@vueuse/components": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-11.1.0.tgz", - "integrity": "sha512-8CTbvH1rHfAlqsMdMg6G2OiIvHiHn8HRx0yyJ+Ri/C8J6cLylXAd7VESawoCAkRdAXT4ucPnj/uYHZqEb0JbBQ==", - "dependencies": { - "@vueuse/core": "11.1.0", - "@vueuse/shared": "11.1.0", - "vue-demi": ">=0.14.10" - } - }, - "node_modules/@vueuse/components/node_modules/vue-demi": { - "version": "0.14.10", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", - "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } - } - }, "node_modules/@vueuse/core": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-11.1.0.tgz", @@ -3949,7 +4243,8 @@ "node_modules/@yr/monotone-cubic-spline": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz", - "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==" + "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==", + "peer": true }, "node_modules/abbrev": { "version": "2.0.0", @@ -4117,9 +4412,10 @@ } }, "node_modules/apexcharts": { - "version": "3.54.0", - "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.54.0.tgz", - "integrity": "sha512-ZgI/seScffjLpwNRX/gAhIkAhpCNWiTNsdICv7qxnF0xisI23XSsaENUKIcMlyP1rbe8ECgvybDnp7plZld89A==", + "version": "3.54.1", + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.54.1.tgz", + "integrity": "sha512-E4et0h/J1U3r3EwS/WlqJCQIbepKbp6wGUmaAwJOMjHUP4Ci0gxanLa7FR3okx6p9coi4st6J853/Cb1NP0vpA==", + "peer": true, "dependencies": { "@yr/monotone-cubic-spline": "^1.0.3", "svg.draggable.js": "^2.2.2", @@ -4166,9 +4462,22 @@ "dev": true }, "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true, + "engines": { + "node": ">=8" + } }, "node_modules/array-union": { "version": "2.1.0", @@ -4178,6 +4487,15 @@ "node": ">=8" } }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", @@ -4347,9 +4665,9 @@ } }, "node_modules/birpc": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/birpc/-/birpc-0.2.17.tgz", - "integrity": "sha512-+hkTxhot+dWsLpp3gia5AkVHIsKlZybNT5gIYiDlNzJrmYPcTM9k5/w2uaj3IPpd7LlEYpmCj4Jj1nC41VhDFg==", + "version": "0.2.19", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-0.2.19.tgz", + "integrity": "sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/antfu" @@ -4582,6 +4900,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -4590,6 +4917,18 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -4600,9 +4939,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001664", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz", - "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==", + "version": "1.0.30001668", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001668.tgz", + "integrity": "sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==", "funding": [ { "type": "opencollective", @@ -5021,9 +5360,9 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/confbox": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", - "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==" + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==" }, "node_modules/config-chain": { "version": "1.1.13", @@ -5122,6 +5461,22 @@ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", "dev": true }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -5533,9 +5888,9 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, "node_modules/deep-pick-omit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/deep-pick-omit/-/deep-pick-omit-1.2.0.tgz", - "integrity": "sha512-2CGvfTM2c+IP/MhdRZMpaHhTc6zIlgz3tQXJ/VGAkc7mjMrjqSU28qiI63yEcy+fcYfd/K+NNJcGRzap4M4bqw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/deep-pick-omit/-/deep-pick-omit-1.2.1.tgz", + "integrity": "sha512-2J6Kc/m3irCeqVG42T+SaUMesaK7oGWaedGnQQK/+O0gYc+2SP5bKh/KKTE7d7SJ+GCA9UUE1GRzh6oDe0EnGw==" }, "node_modules/default-browser": { "version": "5.2.1", @@ -5610,6 +5965,146 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true }, + "node_modules/depcheck": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/depcheck/-/depcheck-1.4.7.tgz", + "integrity": "sha512-1lklS/bV5chOxwNKA/2XUUk/hPORp8zihZsXflr8x0kLwmcZ9Y9BsS6Hs3ssvA+2wUVbG0U2Ciqvm1SokNjPkA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.23.0", + "@babel/traverse": "^7.23.2", + "@vue/compiler-sfc": "^3.3.4", + "callsite": "^1.0.0", + "camelcase": "^6.3.0", + "cosmiconfig": "^7.1.0", + "debug": "^4.3.4", + "deps-regex": "^0.2.0", + "findup-sync": "^5.0.0", + "ignore": "^5.2.4", + "is-core-module": "^2.12.0", + "js-yaml": "^3.14.1", + "json5": "^2.2.3", + "lodash": "^4.17.21", + "minimatch": "^7.4.6", + "multimatch": "^5.0.0", + "please-upgrade-node": "^3.2.0", + "readdirp": "^3.6.0", + "require-package-name": "^2.0.1", + "resolve": "^1.22.3", + "resolve-from": "^5.0.0", + "semver": "^7.5.4", + "yargs": "^16.2.0" + }, + "bin": { + "depcheck": "bin/depcheck.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/depcheck/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/depcheck/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/depcheck/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/depcheck/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/depcheck/node_modules/minimatch": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", + "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/depcheck/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/depcheck/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/depcheck/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -5619,6 +6114,12 @@ "node": ">= 0.8" } }, + "node_modules/deps-regex": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/deps-regex/-/deps-regex-0.2.0.tgz", + "integrity": "sha512-PwuBojGMQAYbWkMXOY9Pd/NWCDNHVH12pnS7WHqZkTSeMESe4hwnKKRp0yR87g37113x4JPbo/oIvXY+s/f56Q==", + "dev": true + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -5642,6 +6143,27 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/detect-touch-device": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/detect-touch-device/-/detect-touch-device-1.1.6.tgz", @@ -5676,14 +6198,6 @@ "node": ">=8" } }, - "node_modules/dir-glob/node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } - }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -5852,9 +6366,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.5.29", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz", - "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==" + "version": "1.5.38", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.38.tgz", + "integrity": "sha512-VbeVexmZ1IFh+5EfrYz1I0HTzHVIlJa112UEWhciPyeOcKJGeTv6N8WnG4wsQB81DGCaVEGhpSb6o6a8WYFXXg==" }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -6026,20 +6540,20 @@ } }, "node_modules/eslint": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz", - "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", + "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.6.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.11.1", + "@eslint/js": "9.12.0", "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", + "@humanwhocodes/retry": "^0.3.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -6047,9 +6561,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.2", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -6059,13 +6573,11 @@ "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", "text-table": "^0.2.0" }, "bin": { @@ -6274,12 +6786,12 @@ "dev": true }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.0.tgz", - "integrity": "sha512-P7qDB/RckdKETpBM4CtjHRQ5qXByPmFhRi86sN3E+J+tySchq+RSOGGhI2hDIefmmKFuTi/1ACjqsnDJDDDfzg==", + "version": "50.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.4.1.tgz", + "integrity": "sha512-OXIq+JJQPCLAKL473/esioFOwbXyRE5MAQ4HbZjcp3e+K3zdxt2uDpGs3FR+WezUXNStzEtTfgx15T+JFrVwBA==", "dev": true, "dependencies": { - "@es-joy/jsdoccomment": "~0.48.0", + "@es-joy/jsdoccomment": "~0.49.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.3.6", @@ -6298,10 +6810,24 @@ "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-jsdoc/node_modules/@es-joy/jsdoccomment": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz", + "integrity": "sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==", + "dev": true, + "dependencies": { + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~4.1.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/eslint-plugin-jsdoc/node_modules/synckit": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", - "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", "dev": true, "dependencies": { "@pkgr/core": "^0.1.0", @@ -6392,9 +6918,9 @@ "dev": true }, "node_modules/eslint-plugin-n": { - "version": "17.10.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.10.3.tgz", - "integrity": "sha512-ySZBfKe49nQZWR1yFaA0v/GsH6Fgp8ah6XV0WDz6CN8WO0ek4McMzb7A2xnf4DCYV43frjCygvb9f/wx7UUxRw==", + "version": "17.11.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.11.1.tgz", + "integrity": "sha512-93IUD82N6tIEgjztVI/l3ElHtC2wTa9boJHrD8iN+NyDxjxz/daZUZKfkedjBZNdg6EqDk4irybUsiPwDqXAEA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", @@ -6426,13 +6952,13 @@ } }, "node_modules/eslint-plugin-perfectionist": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-3.7.0.tgz", - "integrity": "sha512-pemhfcR3LDbYVWeveHok9u048yR7GpsnfyPvn6RsDkp/UV7iqBV0y5K0aGb9ZJMsemOyWok7akxGzPLsz+mHKQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-3.8.0.tgz", + "integrity": "sha512-BYJWbQVOjvIGK9V1xUfn790HuvkePjxti8epOi1H6sdzo0N4RehBmQ8coHPbgA/f12BUG1NIoDtQhI9mUm+o2A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "^8.7.0", - "@typescript-eslint/utils": "^8.7.0", + "@typescript-eslint/types": "^8.8.0", + "@typescript-eslint/utils": "^8.8.0", "minimatch": "^9.0.5", "natural-compare-lite": "^1.4.0" }, @@ -6491,9 +7017,9 @@ } }, "node_modules/eslint-plugin-prettier/node_modules/synckit": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", - "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" @@ -6585,18 +7111,6 @@ "eslint": ">=8.56.0" } }, - "node_modules/eslint-plugin-unicorn/node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/eslint-plugin-unused-imports": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz", @@ -6613,9 +7127,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "9.28.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.28.0.tgz", - "integrity": "sha512-ShrihdjIhOTxs+MfWun6oJWuk+g/LAhN+CiuOl/jjkG3l0F2AuK5NMTaWqyvBgkFtpYmyks6P4603mLmhNJW8g==", + "version": "9.29.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.29.0.tgz", + "integrity": "sha512-hamyjrBhNH6Li6R1h1VF9KHfshJlKgKEg3ARbGTn72CMNDSMhWbgC7NdkRDEh25AFW+4SDATzyNM+3gWuZii8g==", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "globals": "^13.24.0", @@ -6720,9 +7234,9 @@ } }, "node_modules/eslint/node_modules/@eslint/js": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz", - "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", + "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -6827,6 +7341,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/esquery": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", @@ -6931,6 +7458,18 @@ "node": ">=4" } }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -7107,6 +7646,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/findup-sync": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", + "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.3", + "micromatch": "^4.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 10.13.0" + } + }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", @@ -7200,9 +7754,9 @@ } }, "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": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -7325,15 +7879,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -7462,10 +8007,58 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/globals": { - "version": "15.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.10.0.tgz", - "integrity": "sha512-tqFIbz83w4Y5TCbtgjZjApohbuh7K9BxGYFm7ifwDR240tvdb7P9x+/9VvUKlmkPoiknoJtanI8UOrqxS3a7lQ==", + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", + "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", "dev": true, "engines": { "node": ">=18" @@ -7493,6 +8086,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globby/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -7645,7 +8249,19 @@ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.10.0.tgz", "integrity": "sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==", "engines": { - "node": ">=12.0.0" + "node": ">=12.0.0" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, "node_modules/hookable": { @@ -7880,6 +8496,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, "node_modules/import-from-esm": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/import-from-esm/-/import-from-esm-1.3.4.tgz", @@ -7921,9 +8545,9 @@ } }, "node_modules/importx/node_modules/jiti": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.0.0.tgz", - "integrity": "sha512-CJ7e7Abb779OTRv3lomfp7Mns/Sy1+U4pcAx5VbjxCZD5ZM/VJaXPpPjNKjtSvWQy/H86E49REXR34dl1JEz9w==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.3.3.tgz", + "integrity": "sha512-EX4oNDwcXSivPrw2qKH2LB5PoFxEvgtv2JgwW0bU858HoLQ+kutSvjLMUqBd0PeJYEinLWhoI9Ol0eYMqj/wNQ==", "dev": true, "bin": { "jiti": "lib/jiti-cli.mjs" @@ -8215,6 +8839,15 @@ "url": "https://github.com/sponsors/mesqueeb" } }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -8275,9 +8908,9 @@ } }, "node_modules/jose": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.9.3.tgz", - "integrity": "sha512-egLIoYSpcd+QUF+UHgobt5YzI2Pkw/H39ou9suW687MY6PmCwPmkNV/4TNjn1p2tX5xO3j0d0sq5hiYE24bSlg==", + "version": "5.9.4", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.9.4.tgz", + "integrity": "sha512-WBBl6au1qg6OHj67yCffCgFR3BADJBXN8MdRvCgJDuMv3driV2nHr7jdGvaKX9IolosAsn+M0XRArqLXUhyJHQ==", "funding": { "url": "https://github.com/sponsors/panva" } @@ -8323,11 +8956,13 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "dependencies": { - "argparse": "^2.0.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" @@ -8410,14 +9045,14 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { @@ -8426,13 +9061,10 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, "node_modules/json-parse-even-better-errors": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", - "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "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 }, "node_modules/json-schema": { "version": "0.4.0", @@ -9096,13 +9728,10 @@ } }, "node_modules/loupe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", - "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.1" - } + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", + "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "dev": true }, "node_modules/lru-cache": { "version": "5.1.1", @@ -9121,9 +9750,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } @@ -9150,6 +9779,11 @@ "markdown-it": "bin/markdown-it.mjs" } }, + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "node_modules/markdown-table": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", @@ -10128,14 +10762,14 @@ } }, "node_modules/mlly": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", - "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.2.tgz", + "integrity": "sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA==", "dependencies": { - "acorn": "^8.11.3", + "acorn": "^8.12.1", "pathe": "^1.1.2", - "pkg-types": "^1.1.1", - "ufo": "^1.5.3" + "pkg-types": "^1.2.0", + "ufo": "^1.5.4" } }, "node_modules/mri": { @@ -10166,6 +10800,47 @@ "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", "dev": true }, + "node_modules/multimatch": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", + "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", + "dev": true, + "dependencies": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/multimatch/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/multimatch/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -10207,9 +10882,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", "funding": [ { "type": "github", @@ -10217,10 +10892,10 @@ } ], "bin": { - "nanoid": "bin/nanoid.cjs" + "nanoid": "bin/nanoid.js" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": "^18 || >=20" } }, "node_modules/natural-compare": { @@ -10243,6 +10918,12 @@ "node": ">= 0.6" } }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true + }, "node_modules/node-fetch-native": { "version": "1.6.4", "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", @@ -10555,9 +11236,9 @@ } }, "node_modules/ofetch": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.0.tgz", - "integrity": "sha512-MuHgsEhU6zGeX+EMh+8mSMrYTnsqJQQrpM00Q6QHMKNqQ0bKy0B43tk8tL1wg+CnsSTy1kg4Ir2T5Ig6rD+dfQ==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz", + "integrity": "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==", "dev": true, "dependencies": { "destr": "^2.0.3", @@ -10719,9 +11400,9 @@ "dev": true }, "node_modules/package-manager-detector": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.0.tgz", - "integrity": "sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.2.tgz", + "integrity": "sha512-VgXbyrSNsml4eHWIvxxG/nTL4wgybMTXCV2Un/+yEc3aDKKU6nQBZjbeP3Pl3qm9Qg92X/1ng4ffvCeD/zwHgg==", "dev": true }, "node_modules/parent-module": { @@ -10775,19 +11456,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-json/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 + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.0.tgz", + "integrity": "sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==", "dev": true, "dependencies": { - "entities": "^4.4.0" + "entities": "^4.5.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -10875,14 +11559,11 @@ "dev": true }, "node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/pathe": { @@ -10989,12 +11670,12 @@ } }, "node_modules/pinia-plugin-persistedstate": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-4.0.2.tgz", - "integrity": "sha512-KSApXsnGTrWKnAeHgEpYqtzeO84y4NH7uVM0/KMog+/oR2Py8p25tKjHQUmkcNNluzc0rJjFzlv2i5ZTdLeTXA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-4.1.1.tgz", + "integrity": "sha512-fUiUsbfBetGUZzX28z+ImAZw7FDXzwRrk+fN+ljF5OhQMhsSYfYeUzI9FLLtpjekYbfFHWvJiECkLI60RIuiPA==", "dependencies": { "@nuxt/kit": "^3.13.2", - "deep-pick-omit": "^1.2.0", + "deep-pick-omit": "^1.2.1", "defu": "^6.1.4", "destr": "^2.0.3" }, @@ -11046,15 +11727,24 @@ } }, "node_modules/pkg-types": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.0.tgz", - "integrity": "sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.1.tgz", + "integrity": "sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==", "dependencies": { - "confbox": "^0.1.7", - "mlly": "^1.7.1", + "confbox": "^0.1.8", + "mlly": "^1.7.2", "pathe": "^1.1.2" } }, + "node_modules/please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "dependencies": { + "semver-compare": "^1.0.0" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -11206,6 +11896,18 @@ "url": "https://github.com/sponsors/antonk52" } }, + "node_modules/postcss-load-config/node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/postcss-nested": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", @@ -11249,6 +11951,23 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -11441,6 +12160,15 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -11578,9 +12306,9 @@ } }, "node_modules/regex": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.2.tgz", - "integrity": "sha512-kK/AA3A9K6q2js89+VMymcboLOlF5lZRCYJv3gzszXFHBr6kO6qLGzbm+UIugBEV8SMMKCTR59txoY6ctRHYVw==" + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", + "integrity": "sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==" }, "node_modules/regexp-ast-analysis": { "version": "0.7.1", @@ -11773,6 +12501,12 @@ "node": ">=0.10.0" } }, + "node_modules/require-package-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz", + "integrity": "sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==", + "dev": true + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -11796,12 +12530,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/resolve-path": { @@ -11959,9 +12707,9 @@ } }, "node_modules/rollup": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.5.tgz", - "integrity": "sha512-WoinX7GeQOFMGznEcWA1WrTQCd/tpEbMkc3nuMs9BT0CPjMdSjPMTVClwWd4pgSQwJdP65SK9mTCNvItlr5o7w==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", "devOptional": true, "dependencies": { "@types/estree": "1.0.6" @@ -11974,22 +12722,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.5", - "@rollup/rollup-android-arm64": "4.22.5", - "@rollup/rollup-darwin-arm64": "4.22.5", - "@rollup/rollup-darwin-x64": "4.22.5", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.5", - "@rollup/rollup-linux-arm-musleabihf": "4.22.5", - "@rollup/rollup-linux-arm64-gnu": "4.22.5", - "@rollup/rollup-linux-arm64-musl": "4.22.5", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.5", - "@rollup/rollup-linux-riscv64-gnu": "4.22.5", - "@rollup/rollup-linux-s390x-gnu": "4.22.5", - "@rollup/rollup-linux-x64-gnu": "4.22.5", - "@rollup/rollup-linux-x64-musl": "4.22.5", - "@rollup/rollup-win32-arm64-msvc": "4.22.5", - "@rollup/rollup-win32-ia32-msvc": "4.22.5", - "@rollup/rollup-win32-x64-msvc": "4.22.5", + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", "fsevents": "~2.3.2" } }, @@ -12048,19 +12796,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.5", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.5.tgz", - "integrity": "sha512-N0jPPhHjGShcB9/XXZQWuWBKZQnC1F36Ce3sDqWpujsGjDz/CQtOL9LgTrJ+rJC8MJeesMWrMWVLKKNR/tMOCA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/rrweb-cssom": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", @@ -12137,11 +12872,12 @@ "dev": true }, "node_modules/sass": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.4.tgz", - "integrity": "sha512-K0QDSNPXgyqO4GZq2HO5Q70TLxTH6cIT59RdoCHMivrC8rqzaTw5ab9prjz9KUN1El4FLXrBXJhik61JR4HcGg==", + "version": "1.79.5", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.5.tgz", + "integrity": "sha512-W1h5kp6bdhqFh2tk3DsI771MoEJjvrSY/2ihJRJS4pjIyfJCw0nTsxqhnrUzaLMOJjFchj8rOvraI/YUVjtx5g==", "dev": true, "dependencies": { + "@parcel/watcher": "^2.4.1", "chokidar": "^4.0.0", "immutable": "^4.0.0", "source-map-js": ">=0.6.2 <2.0.0" @@ -12169,9 +12905,9 @@ } }, "node_modules/sass/node_modules/readdirp": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz", - "integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "dev": true, "engines": { "node": ">= 14.16.0" @@ -12225,9 +12961,9 @@ } }, "node_modules/seemly": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/seemly/-/seemly-0.3.8.tgz", - "integrity": "sha512-MW8Qs6vbzo0pHmDpFSYPna+lwpZ6Zk1ancbajw/7E8TKtHdV+1DfZZD+kKJEhG/cAoB/i+LiT+5msZOqj0DwRA==" + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/seemly/-/seemly-0.3.9.tgz", + "integrity": "sha512-bMLcaEqhIViiPbaumjLN8t1y+JpD/N8SiyYOyp0i0W6RgdyLWboIsUWAbZojF//JyerxPZR5Tgda+x3Pdne75A==" }, "node_modules/semver": { "version": "7.6.3", @@ -12240,6 +12976,12 @@ "node": ">=10" } }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -12292,15 +13034,15 @@ } }, "node_modules/shiki": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.21.0.tgz", - "integrity": "sha512-apCH5BoWTrmHDPGgg3RF8+HAAbEL/CdbYr8rMw7eIrdhCkZHdVGat5mMNlRtd1erNG01VPMIKHNQ0Pj2HMAiog==", - "dependencies": { - "@shikijs/core": "1.21.0", - "@shikijs/engine-javascript": "1.21.0", - "@shikijs/engine-oniguruma": "1.21.0", - "@shikijs/types": "1.21.0", - "@shikijs/vscode-textmate": "^9.2.2", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.0.tgz", + "integrity": "sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==", + "dependencies": { + "@shikijs/core": "1.22.0", + "@shikijs/engine-javascript": "1.22.0", + "@shikijs/engine-oniguruma": "1.22.0", + "@shikijs/types": "1.22.0", + "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4" } }, @@ -12512,6 +13254,12 @@ "node": "*" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, "node_modules/sshpk": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", @@ -12830,6 +13578,7 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz", "integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==", + "peer": true, "dependencies": { "svg.js": "^2.0.1" }, @@ -12841,6 +13590,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz", "integrity": "sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==", + "peer": true, "dependencies": { "svg.js": ">=2.3.x" }, @@ -12852,6 +13602,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz", "integrity": "sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==", + "peer": true, "dependencies": { "svg.js": "^2.2.5" }, @@ -12862,12 +13613,14 @@ "node_modules/svg.js": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz", - "integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==" + "integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==", + "peer": true }, "node_modules/svg.pathmorphing.js": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz", "integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==", + "peer": true, "dependencies": { "svg.js": "^2.4.0" }, @@ -12879,6 +13632,7 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz", "integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==", + "peer": true, "dependencies": { "svg.js": "^2.6.5", "svg.select.js": "^2.1.2" @@ -12891,6 +13645,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz", "integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==", + "peer": true, "dependencies": { "svg.js": "^2.2.5" }, @@ -12902,6 +13657,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz", "integrity": "sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==", + "peer": true, "dependencies": { "svg.js": "^2.6.5" }, @@ -13117,6 +13873,24 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/taze/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/taze/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/taze/node_modules/unconfig": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-0.6.0.tgz", @@ -13212,21 +13986,21 @@ } }, "node_modules/tldts": { - "version": "6.1.48", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.48.tgz", - "integrity": "sha512-SPbnh1zaSzi/OsmHb1vrPNnYuwJbdWjwo5TbBYYMlTtH3/1DSb41t8bcSxkwDmmbG2q6VLPVvQc7Yf23T+1EEw==", + "version": "6.1.51", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.51.tgz", + "integrity": "sha512-33lfQoL0JsDogIbZ8fgRyvv77GnRtwkNE/MOKocwUgPO1WrSfsq7+vQRKxRQZai5zd+zg97Iv9fpFQSzHyWdLA==", "dev": true, "dependencies": { - "tldts-core": "^6.1.48" + "tldts-core": "^6.1.51" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.48", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.48.tgz", - "integrity": "sha512-3gD9iKn/n2UuFH1uilBviK9gvTNT6iYwdqrj1Vr5mh8FuelvpRNaYVH4pNYqUgOGU4aAdL9X35eLuuj0gRsx+A==", + "version": "6.1.51", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.51.tgz", + "integrity": "sha512-bu9oCYYWC1iRjx+3UnAjqCsfrWNZV1ghNQf49b3w5xE8J/tNShHTzp5syWJfwGH+pxUgTTLUnzHnfuydW7wmbg==", "dev": true }, "node_modules/tmp": { @@ -14117,15 +14891,15 @@ } }, "node_modules/untyped": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/untyped/-/untyped-1.5.0.tgz", - "integrity": "sha512-o2Vjmn2dal08BzCcINxSmWuAteReUUiXseii5VRhmxyLF0b21K0iKZQ9fMYK7RWspVkY+0saqaVQNq4roe3Efg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/untyped/-/untyped-1.5.1.tgz", + "integrity": "sha512-reBOnkJBFfBZ8pCKaeHgfZLcehXtM6UTxc+vqs1JvCps0c4amLNp3fhdGBZwYp+VLyoY9n3X5KOP7lCyWBUX9A==", "dependencies": { - "@babel/core": "^7.25.2", - "@babel/standalone": "^7.25.6", - "@babel/types": "^7.25.6", + "@babel/core": "^7.25.7", + "@babel/standalone": "^7.25.7", + "@babel/types": "^7.25.7", "defu": "^6.1.4", - "jiti": "^2.0.0", + "jiti": "^2.3.1", "mri": "^1.2.0", "scule": "^1.3.0" }, @@ -14134,9 +14908,9 @@ } }, "node_modules/untyped/node_modules/jiti": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.0.0.tgz", - "integrity": "sha512-CJ7e7Abb779OTRv3lomfp7Mns/Sy1+U4pcAx5VbjxCZD5ZM/VJaXPpPjNKjtSvWQy/H86E49REXR34dl1JEz9w==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.3.3.tgz", + "integrity": "sha512-EX4oNDwcXSivPrw2qKH2LB5PoFxEvgtv2JgwW0bU858HoLQ+kutSvjLMUqBd0PeJYEinLWhoI9Ol0eYMqj/wNQ==", "bin": { "jiti": "lib/jiti-cli.mjs" } @@ -14291,9 +15065,9 @@ } }, "node_modules/vite": { - "version": "5.4.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz", - "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", + "version": "5.4.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.9.tgz", + "integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==", "dev": true, "dependencies": { "esbuild": "^0.21.3", @@ -14349,12 +15123,6 @@ } } }, - "node_modules/vite-bundle-analyzer": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/vite-bundle-analyzer/-/vite-bundle-analyzer-0.12.1.tgz", - "integrity": "sha512-mIYwsDvTYCqXAUtOZIL3f7NdwWUeL/MlNFhOJzlTdcZE4pye6h06IEnOvWhnc/e+HM4oVVNxuRHZt0Rz6VO7EA==", - "dev": true - }, "node_modules/vite-bundle-visualizer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/vite-bundle-visualizer/-/vite-bundle-visualizer-1.2.1.tgz", @@ -14386,9 +15154,9 @@ } }, "node_modules/vite-node": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.2.tgz", - "integrity": "sha512-HPcGNN5g/7I2OtPjLqgOtCRu/qhVvBxTUD3qzitmL0SrG1cWFzxzhMDWussxSbrRYWqnKf8P2jiNhPMSN+ymsQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz", + "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==", "dev": true, "dependencies": { "cac": "^6.7.14", @@ -14670,18 +15438,18 @@ } }, "node_modules/vitest": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.2.tgz", - "integrity": "sha512-veNjLizOMkRrJ6xxb+pvxN6/QAWg95mzcRjtmkepXdN87FNfxAss9RKe2far/G9cQpipfgP2taqg0KiWsquj8A==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz", + "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==", "dev": true, "dependencies": { - "@vitest/expect": "2.1.2", - "@vitest/mocker": "2.1.2", - "@vitest/pretty-format": "^2.1.2", - "@vitest/runner": "2.1.2", - "@vitest/snapshot": "2.1.2", - "@vitest/spy": "2.1.2", - "@vitest/utils": "2.1.2", + "@vitest/expect": "2.1.3", + "@vitest/mocker": "2.1.3", + "@vitest/pretty-format": "^2.1.3", + "@vitest/runner": "2.1.3", + "@vitest/snapshot": "2.1.3", + "@vitest/spy": "2.1.3", + "@vitest/utils": "2.1.3", "chai": "^5.1.1", "debug": "^4.3.6", "magic-string": "^0.30.11", @@ -14692,7 +15460,7 @@ "tinypool": "^1.0.0", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.1.2", + "vite-node": "2.1.3", "why-is-node-running": "^2.3.0" }, "bin": { @@ -14707,8 +15475,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.2", - "@vitest/ui": "2.1.2", + "@vitest/browser": "2.1.3", + "@vitest/ui": "2.1.3", "happy-dom": "*", "jsdom": "*" }, @@ -14751,15 +15519,15 @@ "dev": true }, "node_modules/vue": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.10.tgz", - "integrity": "sha512-Vy2kmJwHPlouC/tSnIgXVg03SG+9wSqT1xu1Vehc+ChsXsRd7jLkKgMltVEFOzUdBr3uFwBCG+41LJtfAcBRng==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.12.tgz", + "integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==", "dependencies": { - "@vue/compiler-dom": "3.5.10", - "@vue/compiler-sfc": "3.5.10", - "@vue/runtime-dom": "3.5.10", - "@vue/server-renderer": "3.5.10", - "@vue/shared": "3.5.10" + "@vue/compiler-dom": "3.5.12", + "@vue/compiler-sfc": "3.5.12", + "@vue/runtime-dom": "3.5.12", + "@vue/server-renderer": "3.5.12", + "@vue/shared": "3.5.12" }, "peerDependencies": { "typescript": "*" @@ -14870,12 +15638,12 @@ } }, "node_modules/vue-i18n": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-10.0.3.tgz", - "integrity": "sha512-8ul2S4Hy9orKs7eOlkw/zqnVu98GttUdyIMRyjoMpv6hFPxnybgBLdep/UCmdan5kUHyxqMnr2cGHTBuPBYJaw==", + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-10.0.4.tgz", + "integrity": "sha512-1xkzVxqBLk2ZFOmeI+B5r1J7aD/WtNJ4j9k2mcFcQo5BnOmHBmD7z4/oZohh96AAaRZ4Q7mNQvxc9h+aT+Md3w==", "dependencies": { - "@intlify/core-base": "10.0.3", - "@intlify/shared": "10.0.3", + "@intlify/core-base": "10.0.4", + "@intlify/shared": "10.0.4", "@vue/devtools-api": "^6.5.0" }, "engines": { @@ -14928,9 +15696,9 @@ } }, "node_modules/vue3-apexcharts": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/vue3-apexcharts/-/vue3-apexcharts-1.6.0.tgz", - "integrity": "sha512-gemKFXpw4TuVcllwyKJGYjTwiJQxxCUwbXsiiEEZjs0zc9jvOHvreN8frXz7QbnYqMqOHF9D1TBqwENvoPNjLw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vue3-apexcharts/-/vue3-apexcharts-1.7.0.tgz", + "integrity": "sha512-BmWoS8+x5XLCtk2ml7rLVO+QU+fjgQUUCjUXSFW9cNQpCMa5Z0eRPvZjvYLt5aDKNREtuZoidlG9WRjZ/Af7lA==", "peerDependencies": { "apexcharts": "> 3.0.0", "vue": "> 3.0.0" @@ -15286,15 +16054,12 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, - "bin": { - "yaml": "bin.mjs" - }, "engines": { - "node": ">= 14" + "node": ">= 6" } }, "node_modules/yaml-eslint-parser": { @@ -15326,6 +16091,18 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/yaml-eslint-parser/node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index eaa97599..ce625e2a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -28,7 +28,7 @@ "start-server": "cd ../backend && /opt/venv/bin/python copilot.py", "start-vue": "vite --host 0.0.0.0", "start": "concurrently \"npm run start-server\" \"npm run start-vue\"", - "libs-check": "taze", + "libs-check": "taze && depcheck", "libs-reload": "rm -rf node_modules package-lock.json && npm install", "open:swagger": "open http://127.0.0.1:5000/docs#/", "open:redoc": "open http://127.0.0.1:5000/redoc", @@ -37,41 +37,38 @@ "dependencies": { "@ajoelp/json-to-formdata": "^1.5.0", "@f3ve/vue-markdown-it": "^0.2.2", - "@fontsource/jetbrains-mono": "^5.1.0", - "@fontsource/lexend": "^5.1.0", - "@fontsource/public-sans": "^5.1.0", - "@popperjs/core": "^2.11.8", - "@shikijs/markdown-it": "^1.21.0", - "@vueuse/components": "^11.1.0", + "@fontsource/jetbrains-mono": "^5.1.1", + "@fontsource/lexend": "^5.1.1", + "@fontsource/public-sans": "^5.1.1", + "@shikijs/markdown-it": "^1.22.0", "@vueuse/core": "^11.1.0", - "apexcharts": "^3.54.0", "axios": "^1.7.7", "bytes": "^3.1.2", "colord": "^2.9.3", - "crypto-js": "^4.2.0", "dayjs": "^1.11.13", "detect-touch-device": "^1.1.6", "echarts": "^5.5.1", "file-saver": "^2.0.5", "html-entities": "^2.5.2", - "jose": "^5.9.3", + "jose": "^5.9.4", "js-md5": "^0.8.3", "lodash": "^4.17.21", "mitt": "^3.0.1", "naive-ui": "^2.40.1", + "nanoid": "^5.0.7", "password-validator": "^5.3.0", "pinia": "^2.2.4", - "pinia-plugin-persistedstate": "^4.0.2", + "pinia-plugin-persistedstate": "^4.1.1", "secure-ls": "^2.0.0", - "shiki": "^1.21.0", + "shiki": "^1.22.0", "validator": "^13.12.0", - "vue": "^3.5.10", + "vue": "^3.5.12", "vue-advanced-cropper": "^2.8.9", "vue-highlight-words": "^3.0.1", - "vue-i18n": "^10.0.3", + "vue-i18n": "^10.0.4", "vue-router": "^4.4.5", "vue-sjv": "^0.0.6", - "vue3-apexcharts": "^1.6.0", + "vue3-apexcharts": "^1.7.0", "vue3-marquee": "^4.2.2", "vuedraggable": "^4.1.0" }, @@ -86,10 +83,9 @@ "@types/bytes": "^3.1.4", "@types/file-saver": "^2.0.7", "@types/fs-extra": "^11.0.4", - "@types/inquirer": "^9.0.7", "@types/jsdom": "^21.1.7", "@types/lodash": "^4.17.10", - "@types/node": "^22.7.4", + "@types/node": "^22.7.5", "@types/validator": "^13.12.2", "@vitejs/plugin-vue": "^5.1.4", "@vitejs/plugin-vue-jsx": "^4.0.1", @@ -97,17 +93,15 @@ "@vue/tsconfig": "^0.5.1", "autoprefixer": "^10.4.20", "cypress": "^13.15.0", - "eslint": "^9.11.1", + "depcheck": "^1.4.7", + "eslint": "^9.12.0", "flourite": "^1.3.0", "fs-extra": "^11.2.0", - "globals": "^15.10.0", "jsdom": "^25.0.1", - "json5": "^2.2.3", "npm-run-all2": "^6.2.3", - "picocolors": "^1.1.0", "postcss": "^8.4.47", "prettier": "^3.3.3", - "sass": "^1.79.4", + "sass": "^1.79.5", "start-server-and-test": "^2.0.8", "tailwind-config-viewer": "^2.0.4", "tailwindcss": "^3.4.13", @@ -115,29 +109,28 @@ "type-fest": "^4.26.1", "typescript": "~5.5.4", "unplugin-vue-components": "^0.27.4", - "vite": "^5.4.8", - "vite-bundle-analyzer": "^0.12.1", + "vite": "^5.4.9", "vite-bundle-visualizer": "^1.2.1", "vite-plugin-vue-devtools": "^7.4.6", "vite-svg-loader": "^5.1.0", - "vitest": "^2.1.2", + "vitest": "^2.1.3", "vue-tsc": "^2.1.6" }, "pnpm": { "overrides": { - "@typescript-eslint/eslint-plugin": "^8.8.0", + "@typescript-eslint/eslint-plugin": "^8.9.0", "@typescript-eslint/eslint-plugin>eslint": "$eslint", - "@typescript-eslint/parser": "^8.8.0", + "@typescript-eslint/parser": "^8.9.0", "@typescript-eslint/parser>eslint": "$eslint", "eslint": "$eslint" } }, "overrides": { "@typescript-eslint/eslint-plugin": { - "eslint": "9.11.1" + "eslint": "^9.12.0" }, "@typescript-eslint/parser": { - "eslint": "9.11.1" + "eslint": "^9.12.0" } } } From a9a93bb3ba3b3e97a287229519471357c843dcdc Mon Sep 17 00:00:00 2001 From: Davide Di Modica Date: Tue, 15 Oct 2024 12:42:51 +0200 Subject: [PATCH 33/42] feat: add case report api/types --- .../src/api/endpoints/incidentManagement.ts | 46 ++++++++++++++++++- .../src/types/incidentManagement/cases.d.ts | 12 +++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/frontend/src/api/endpoints/incidentManagement.ts b/frontend/src/api/endpoints/incidentManagement.ts index eadcea2e..29ed11d5 100644 --- a/frontend/src/api/endpoints/incidentManagement.ts +++ b/frontend/src/api/endpoints/incidentManagement.ts @@ -9,7 +9,13 @@ import type { AlertTag, AlertTimeline } from "@/types/incidentManagement/alerts.d" -import type { Case, CaseDataStore, CasePayload, CaseStatus } from "@/types/incidentManagement/cases.d" +import type { + Case, + CaseDataStore, + CasePayload, + CaseReportTemplateDataStore, + CaseStatus +} from "@/types/incidentManagement/cases.d" import type { IncidentNotification, IncidentNotificationPayload } from "@/types/incidentManagement/notifications.d" import type { SourceConfiguration, SourceName } from "@/types/incidentManagement/sources.d" import type { KeysOfUnion, UnionToIntersection } from "type-fest" @@ -40,6 +46,12 @@ export type CasesFilterTypes = KeysOfUnion export type AlertCommentPayload = Omit +export interface CaseReportPayload { + case_id: number + file_name: string + template_name: string +} + export default { // #region Sources getConfiguredSources() { @@ -323,6 +335,38 @@ export default { deleteCaseDataStoreFile(caseId: number, fileName: string) { return HttpClient.delete(`/incidents/db_operations/case/data-store/${caseId}/${fileName}`) }, + getCaseReportTemplate() { + return HttpClient.get( + `/incidents/db_operations/case-report-template` + ) + }, + uploadDefaultCaseReportTemplate() { + return HttpClient.post( + `/incidents/db_operations/case-report-template/default-template` + ) + }, + uploadCustomCaseReportTemplate(file: File) { + const form = new FormData() + form.append("file", new Blob([file], { type: file.type }), file.name) + + return HttpClient.post( + `/incidents/db_operations/case-report-template/upload`, + form + ) + }, + downloadCaseReportTemplate(fileName: string) { + return HttpClient.get(`/incidents/db_operations/case-report-template/download/${fileName}`, { + responseType: "blob" + }) + }, + deleteCaseReportTemplate(fileName: string) { + return HttpClient.delete(`/incidents/db_operations/case-report-template/${fileName}`) + }, + generateCaseReportTemplate(payload: CaseReportPayload) { + return HttpClient.post(`/incidents/report/generate-report-docx`, payload, { + responseType: "blob" + }) + }, // #endregion // #region Notification diff --git a/frontend/src/types/incidentManagement/cases.d.ts b/frontend/src/types/incidentManagement/cases.d.ts index c991cfea..e72019da 100644 --- a/frontend/src/types/incidentManagement/cases.d.ts +++ b/frontend/src/types/incidentManagement/cases.d.ts @@ -26,3 +26,15 @@ export interface CaseDataStore { upload_time: Date file_hash: string } + +export interface CaseReportTemplateDataStore { + id: number + report_template_name: string + bucket_name: string + object_key: string + file_name: string + content_type: string + file_size: number + upload_time: Date + file_hash: string +} From 84d2c4976b17221569933f4938c89fda6390917d Mon Sep 17 00:00:00 2001 From: Davide Di Modica Date: Wed, 16 Oct 2024 16:28:14 +0200 Subject: [PATCH 34/42] refactor: case list page --- .../cases/CaseCreationButton.vue | 10 +++--- .../cases/CaseDataStore.vue | 5 +-- .../incidentManagement/cases/CasesExport.vue | 4 +-- .../incidentManagement/cases/CasesList.vue | 35 ++++++++++++++++--- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/frontend/src/components/incidentManagement/cases/CaseCreationButton.vue b/frontend/src/components/incidentManagement/cases/CaseCreationButton.vue index 08b10a55..d1e213d8 100644 --- a/frontend/src/components/incidentManagement/cases/CaseCreationButton.vue +++ b/frontend/src/components/incidentManagement/cases/CaseCreationButton.vue @@ -1,9 +1,9 @@