diff --git a/.kilocode/rules/specify-rules.md b/.kilocode/rules/specify-rules.md index 91f7d5e..2003a85 100644 --- a/.kilocode/rules/specify-rules.md +++ b/.kilocode/rules/specify-rules.md @@ -6,6 +6,8 @@ Auto-generated from all feature plans. Last updated: 2025-12-19 - Python 3.9+, Node.js 18+ + `uvicorn`, `npm`, `bash` (003-project-launch-script) - Python 3.9+, Node.js 18+ + SvelteKit, FastAPI, Tailwind CSS (inferred from existing frontend) (004-integrate-svelte-kit) - N/A (Frontend integration) (004-integrate-svelte-kit) +- Python 3.9+, Node.js 18+ + FastAPI, SvelteKit, Tailwind CSS, Pydantic (001-fix-ui-ws-validation) +- N/A (Configuration based) (001-fix-ui-ws-validation) - Python 3.9+ (Backend), Node.js 18+ (Frontend Build) (001-plugin-arch-svelte-ui) @@ -26,10 +28,10 @@ cd src; pytest; ruff check . Python 3.9+ (Backend), Node.js 18+ (Frontend Build): Follow standard conventions ## Recent Changes +- 001-fix-ui-ws-validation: Added Python 3.9+, Node.js 18+ + FastAPI, SvelteKit, Tailwind CSS, Pydantic +- 001-fix-ui-ws-validation: Added Python 3.9+, Node.js 18+ + FastAPI, SvelteKit, Tailwind CSS, Pydantic - 004-integrate-svelte-kit: Added Python 3.9+, Node.js 18+ + SvelteKit, FastAPI, Tailwind CSS (inferred from existing frontend) -- 003-project-launch-script: Added Python 3.9+, Node.js 18+ + `uvicorn`, `npm`, `bash` -- 001-plugin-arch-svelte-ui: Added Python 3.9+ (Backend), Node.js 18+ (Frontend Build) diff --git a/.specify/memory/constitution.md b/.specify/memory/constitution.md index a4670ff..185414e 100644 --- a/.specify/memory/constitution.md +++ b/.specify/memory/constitution.md @@ -1,50 +1,29 @@ -# [PROJECT_NAME] Constitution - +# ss-tools Constitution ## Core Principles -### [PRINCIPLE_1_NAME] - -[PRINCIPLE_1_DESCRIPTION] - +### I. SPA-First Architecture +The frontend MUST be a Static Single Page Application (SPA) served by the Python backend. No Node.js server is permitted in production. The backend serves the `index.html` entry point for all non-API routes. -### [PRINCIPLE_2_NAME] - -[PRINCIPLE_2_DESCRIPTION] - +### II. API-Driven Communication +All data retrieval and state changes MUST be performed via the backend REST API or WebSockets. The frontend should not access the database or filesystem directly. -### [PRINCIPLE_3_NAME] - -[PRINCIPLE_3_DESCRIPTION] - +### III. Modern Stack Consistency +The project strictly uses SvelteKit (Frontend), FastAPI (Backend), and Tailwind CSS (Styling). New dependencies must be justified and approved. -### [PRINCIPLE_4_NAME] - -[PRINCIPLE_4_DESCRIPTION] - - -### [PRINCIPLE_5_NAME] - -[PRINCIPLE_5_DESCRIPTION] - - -## [SECTION_2_NAME] - - -[SECTION_2_CONTENT] - - -## [SECTION_3_NAME] - - -[SECTION_3_CONTENT] - +### IV. Semantic Protocol Adherence (GRACE-Poly) +All code generation and modification MUST adhere to the Semantic Protocol defined in `semantic_protocol.md`. +- **Anchors**: Use `[DEF:id:Type]` and `[/DEF:id]` to define semantic boundaries. +- **Contracts**: Define `@PRE` and `@POST` conditions in headers. +- **Logging**: Use structured logging with `[AnchorID][State]` format. +- **Immutability**: Respect architectural decisions in headers. ## Governance - -[GOVERNANCE_RULES] - +### Compliance +All Pull Requests and code modifications must be verified against this Constitution. Violations of Core Principles are considered critical defects. -**Version**: [CONSTITUTION_VERSION] | **Ratified**: [RATIFICATION_DATE] | **Last Amended**: [LAST_AMENDED_DATE] - +### Amendments +Changes to this Constitution require a formal RFC process and approval from the project lead. + +**Version**: 1.0.0 | **Ratified**: 2025-12-20 diff --git a/backend/backups/Logs/superset_tool_20251220.log b/backend/backups/Logs/superset_tool_20251220.log index 6e540f6..92ab671 100644 --- a/backend/backups/Logs/superset_tool_20251220.log +++ b/backend/backups/Logs/superset_tool_20251220.log @@ -33,3 +33,237 @@ pydantic_core._pydantic_core.ValidationError: 1 validation error for SupersetCon base_url Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] For further information visit https://errors.pydantic.dev/2.12/v/value_error +2025-12-20 22:42:32,538 - INFO - [BackupPlugin][Entry] Starting backup for superset. +2025-12-20 22:42:32,538 - INFO - [setup_clients][Enter] Starting Superset clients initialization. +2025-12-20 22:42:32,583 - INFO - [setup_clients][Action] Loading environments from ConfigManager +2025-12-20 22:42:32,587 - CRITICAL - [setup_clients][Failure] Critical error during client initialization: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +Traceback (most recent call last): + File "/home/user/ss-tools/superset_tool/utils/init_clients.py", line 66, in setup_clients + config = SupersetConfig( + ^^^^^^^^^^^^^^^ + File "/home/user/ss-tools/backend/.venv/lib/python3.12/site-packages/pydantic/main.py", line 250, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +pydantic_core._pydantic_core.ValidationError: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +2025-12-20 22:54:29,770 - INFO - [BackupPlugin][Entry] Starting backup for . +2025-12-20 22:54:29,771 - INFO - [setup_clients][Enter] Starting Superset clients initialization. +2025-12-20 22:54:29,831 - INFO - [setup_clients][Action] Loading environments from ConfigManager +2025-12-20 22:54:29,833 - CRITICAL - [setup_clients][Failure] Critical error during client initialization: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +Traceback (most recent call last): + File "/home/user/ss-tools/superset_tool/utils/init_clients.py", line 66, in setup_clients + config = SupersetConfig( + ^^^^^^^^^^^^^^^ + File "/home/user/ss-tools/backend/.venv/lib/python3.12/site-packages/pydantic/main.py", line 250, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +pydantic_core._pydantic_core.ValidationError: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +2025-12-20 22:54:34,078 - INFO - [BackupPlugin][Entry] Starting backup for superset. +2025-12-20 22:54:34,078 - INFO - [setup_clients][Enter] Starting Superset clients initialization. +2025-12-20 22:54:34,079 - INFO - [setup_clients][Action] Loading environments from ConfigManager +2025-12-20 22:54:34,079 - CRITICAL - [setup_clients][Failure] Critical error during client initialization: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +Traceback (most recent call last): + File "/home/user/ss-tools/superset_tool/utils/init_clients.py", line 66, in setup_clients + config = SupersetConfig( + ^^^^^^^^^^^^^^^ + File "/home/user/ss-tools/backend/.venv/lib/python3.12/site-packages/pydantic/main.py", line 250, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +pydantic_core._pydantic_core.ValidationError: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +2025-12-20 22:59:25,060 - INFO - [BackupPlugin][Entry] Starting backup for superset. +2025-12-20 22:59:25,060 - INFO - [setup_clients][Enter] Starting Superset clients initialization. +2025-12-20 22:59:25,114 - INFO - [setup_clients][Action] Loading environments from ConfigManager +2025-12-20 22:59:25,117 - CRITICAL - [setup_clients][Failure] Critical error during client initialization: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +Traceback (most recent call last): + File "/home/user/ss-tools/superset_tool/utils/init_clients.py", line 66, in setup_clients + config = SupersetConfig( + ^^^^^^^^^^^^^^^ + File "/home/user/ss-tools/backend/.venv/lib/python3.12/site-packages/pydantic/main.py", line 250, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +pydantic_core._pydantic_core.ValidationError: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +2025-12-20 23:00:31,156 - INFO - [BackupPlugin][Entry] Starting backup for superset. +2025-12-20 23:00:31,156 - INFO - [setup_clients][Enter] Starting Superset clients initialization. +2025-12-20 23:00:31,157 - INFO - [setup_clients][Action] Loading environments from ConfigManager +2025-12-20 23:00:31,162 - CRITICAL - [setup_clients][Failure] Critical error during client initialization: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +Traceback (most recent call last): + File "/home/user/ss-tools/superset_tool/utils/init_clients.py", line 66, in setup_clients + config = SupersetConfig( + ^^^^^^^^^^^^^^^ + File "/home/user/ss-tools/backend/.venv/lib/python3.12/site-packages/pydantic/main.py", line 250, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +pydantic_core._pydantic_core.ValidationError: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +2025-12-20 23:00:34,710 - INFO - [BackupPlugin][Entry] Starting backup for superset. +2025-12-20 23:00:34,710 - INFO - [setup_clients][Enter] Starting Superset clients initialization. +2025-12-20 23:00:34,710 - INFO - [setup_clients][Action] Loading environments from ConfigManager +2025-12-20 23:00:34,711 - CRITICAL - [setup_clients][Failure] Critical error during client initialization: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +Traceback (most recent call last): + File "/home/user/ss-tools/superset_tool/utils/init_clients.py", line 66, in setup_clients + config = SupersetConfig( + ^^^^^^^^^^^^^^^ + File "/home/user/ss-tools/backend/.venv/lib/python3.12/site-packages/pydantic/main.py", line 250, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +pydantic_core._pydantic_core.ValidationError: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +2025-12-20 23:01:43,894 - INFO - [BackupPlugin][Entry] Starting backup for superset. +2025-12-20 23:01:43,894 - INFO - [setup_clients][Enter] Starting Superset clients initialization. +2025-12-20 23:01:43,895 - INFO - [setup_clients][Action] Loading environments from ConfigManager +2025-12-20 23:01:43,895 - CRITICAL - [setup_clients][Failure] Critical error during client initialization: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +Traceback (most recent call last): + File "/home/user/ss-tools/superset_tool/utils/init_clients.py", line 66, in setup_clients + config = SupersetConfig( + ^^^^^^^^^^^^^^^ + File "/home/user/ss-tools/backend/.venv/lib/python3.12/site-packages/pydantic/main.py", line 250, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +pydantic_core._pydantic_core.ValidationError: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +2025-12-20 23:04:07,731 - INFO - [BackupPlugin][Entry] Starting backup for superset. +2025-12-20 23:04:07,731 - INFO - [setup_clients][Enter] Starting Superset clients initialization. +2025-12-20 23:04:07,732 - INFO - [setup_clients][Action] Loading environments from ConfigManager +2025-12-20 23:04:07,732 - CRITICAL - [setup_clients][Failure] Critical error during client initialization: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +Traceback (most recent call last): + File "/home/user/ss-tools/superset_tool/utils/init_clients.py", line 66, in setup_clients + config = SupersetConfig( + ^^^^^^^^^^^^^^^ + File "/home/user/ss-tools/backend/.venv/lib/python3.12/site-packages/pydantic/main.py", line 250, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +pydantic_core._pydantic_core.ValidationError: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +2025-12-20 23:06:39,641 - INFO - [BackupPlugin][Entry] Starting backup for superset. +2025-12-20 23:06:39,642 - INFO - [setup_clients][Enter] Starting Superset clients initialization. +2025-12-20 23:06:39,687 - INFO - [setup_clients][Action] Loading environments from ConfigManager +2025-12-20 23:06:39,689 - CRITICAL - [setup_clients][Failure] Critical error during client initialization: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +Traceback (most recent call last): + File "/home/user/ss-tools/superset_tool/utils/init_clients.py", line 66, in setup_clients + config = SupersetConfig( + ^^^^^^^^^^^^^^^ + File "/home/user/ss-tools/backend/.venv/lib/python3.12/site-packages/pydantic/main.py", line 250, in __init__ + validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +pydantic_core._pydantic_core.ValidationError: 1 validation error for SupersetConfig +base_url + Value error, Invalid URL format: https://superset.bebesh.ru. Must include '/api/v1'. [type=value_error, input_value='https://superset.bebesh.ru', input_type=str] + For further information visit https://errors.pydantic.dev/2.12/v/value_error +2025-12-20 23:30:36,090 - INFO - [BackupPlugin][Entry] Starting backup for superset. +2025-12-20 23:30:36,093 - INFO - [setup_clients][Enter] Starting Superset clients initialization. +2025-12-20 23:30:36,128 - INFO - [setup_clients][Action] Loading environments from ConfigManager +2025-12-20 23:30:36,129 - INFO - [SupersetClient.__init__][Enter] Initializing SupersetClient. +2025-12-20 23:30:36,129 - INFO - [APIClient.__init__][Entry] Initializing APIClient. +2025-12-20 23:30:36,130 - WARNING - [_init_session][State] SSL verification disabled. +2025-12-20 23:30:36,130 - INFO - [APIClient.__init__][Exit] APIClient initialized. +2025-12-20 23:30:36,130 - INFO - [SupersetClient.__init__][Exit] SupersetClient initialized. +2025-12-20 23:30:36,130 - INFO - [get_dashboards][Enter] Fetching dashboards. +2025-12-20 23:30:36,131 - INFO - [authenticate][Enter] Authenticating to https://superset.bebesh.ru/api/v1 +2025-12-20 23:30:36,897 - INFO - [authenticate][Exit] Authenticated successfully. +2025-12-20 23:30:37,527 - INFO - [get_dashboards][Exit] Found 11 dashboards. +2025-12-20 23:30:37,527 - INFO - [BackupPlugin][Progress] Found 11 dashboards to export in superset. +2025-12-20 23:30:37,529 - INFO - [export_dashboard][Enter] Exporting dashboard 11. +2025-12-20 23:30:38,224 - INFO - [export_dashboard][Exit] Exported dashboard 11 to dashboard_export_20251220T203037.zip. +2025-12-20 23:30:38,225 - INFO - [save_and_unpack_dashboard][Enter] Processing dashboard. Unpack: False +2025-12-20 23:30:38,226 - INFO - [save_and_unpack_dashboard][State] Dashboard saved to: backups/SUPERSET/FCC New Coder Survey 2018/dashboard_export_20251220T203037.zip +2025-12-20 23:30:38,227 - INFO - [archive_exports][Enter] Managing archive in backups/SUPERSET/FCC New Coder Survey 2018 +2025-12-20 23:30:38,230 - INFO - [export_dashboard][Enter] Exporting dashboard 10. +2025-12-20 23:30:38,438 - INFO - [export_dashboard][Exit] Exported dashboard 10 to dashboard_export_20251220T203038.zip. +2025-12-20 23:30:38,438 - INFO - [save_and_unpack_dashboard][Enter] Processing dashboard. Unpack: False +2025-12-20 23:30:38,439 - INFO - [save_and_unpack_dashboard][State] Dashboard saved to: backups/SUPERSET/COVID Vaccine Dashboard/dashboard_export_20251220T203038.zip +2025-12-20 23:30:38,439 - INFO - [archive_exports][Enter] Managing archive in backups/SUPERSET/COVID Vaccine Dashboard +2025-12-20 23:30:38,440 - INFO - [export_dashboard][Enter] Exporting dashboard 9. +2025-12-20 23:30:38,853 - INFO - [export_dashboard][Exit] Exported dashboard 9 to dashboard_export_20251220T203038.zip. +2025-12-20 23:30:38,853 - INFO - [save_and_unpack_dashboard][Enter] Processing dashboard. Unpack: False +2025-12-20 23:30:38,856 - INFO - [save_and_unpack_dashboard][State] Dashboard saved to: backups/SUPERSET/Sales Dashboard/dashboard_export_20251220T203038.zip +2025-12-20 23:30:38,856 - INFO - [archive_exports][Enter] Managing archive in backups/SUPERSET/Sales Dashboard +2025-12-20 23:30:38,858 - INFO - [export_dashboard][Enter] Exporting dashboard 8. +2025-12-20 23:30:38,939 - INFO - [export_dashboard][Exit] Exported dashboard 8 to dashboard_export_20251220T203038.zip. +2025-12-20 23:30:38,940 - INFO - [save_and_unpack_dashboard][Enter] Processing dashboard. Unpack: False +2025-12-20 23:30:38,941 - INFO - [save_and_unpack_dashboard][State] Dashboard saved to: backups/SUPERSET/Unicode Test/dashboard_export_20251220T203038.zip +2025-12-20 23:30:38,941 - INFO - [archive_exports][Enter] Managing archive in backups/SUPERSET/Unicode Test +2025-12-20 23:30:38,942 - INFO - [export_dashboard][Enter] Exporting dashboard 7. +2025-12-20 23:30:39,148 - INFO - [export_dashboard][Exit] Exported dashboard 7 to dashboard_export_20251220T203038.zip. +2025-12-20 23:30:39,148 - INFO - [save_and_unpack_dashboard][Enter] Processing dashboard. Unpack: False +2025-12-20 23:30:39,149 - INFO - [save_and_unpack_dashboard][State] Dashboard saved to: backups/SUPERSET/Video Game Sales/dashboard_export_20251220T203038.zip +2025-12-20 23:30:39,149 - INFO - [archive_exports][Enter] Managing archive in backups/SUPERSET/Video Game Sales +2025-12-20 23:30:39,150 - INFO - [export_dashboard][Enter] Exporting dashboard 6. +2025-12-20 23:30:39,689 - INFO - [export_dashboard][Exit] Exported dashboard 6 to dashboard_export_20251220T203039.zip. +2025-12-20 23:30:39,689 - INFO - [save_and_unpack_dashboard][Enter] Processing dashboard. Unpack: False +2025-12-20 23:30:39,690 - INFO - [save_and_unpack_dashboard][State] Dashboard saved to: backups/SUPERSET/Featured Charts/dashboard_export_20251220T203039.zip +2025-12-20 23:30:39,691 - INFO - [archive_exports][Enter] Managing archive in backups/SUPERSET/Featured Charts +2025-12-20 23:30:39,692 - INFO - [export_dashboard][Enter] Exporting dashboard 5. +2025-12-20 23:30:39,960 - INFO - [export_dashboard][Exit] Exported dashboard 5 to dashboard_export_20251220T203039.zip. +2025-12-20 23:30:39,960 - INFO - [save_and_unpack_dashboard][Enter] Processing dashboard. Unpack: False +2025-12-20 23:30:39,961 - INFO - [save_and_unpack_dashboard][State] Dashboard saved to: backups/SUPERSET/Slack Dashboard/dashboard_export_20251220T203039.zip +2025-12-20 23:30:39,961 - INFO - [archive_exports][Enter] Managing archive in backups/SUPERSET/Slack Dashboard +2025-12-20 23:30:39,962 - INFO - [export_dashboard][Enter] Exporting dashboard 4. +2025-12-20 23:30:40,196 - INFO - [export_dashboard][Exit] Exported dashboard 4 to dashboard_export_20251220T203039.zip. +2025-12-20 23:30:40,196 - INFO - [save_and_unpack_dashboard][Enter] Processing dashboard. Unpack: False +2025-12-20 23:30:40,197 - INFO - [save_and_unpack_dashboard][State] Dashboard saved to: backups/SUPERSET/deck.gl Demo/dashboard_export_20251220T203039.zip +2025-12-20 23:30:40,197 - INFO - [archive_exports][Enter] Managing archive in backups/SUPERSET/deck.gl Demo +2025-12-20 23:30:40,198 - INFO - [export_dashboard][Enter] Exporting dashboard 3. +2025-12-20 23:30:40,745 - INFO - [export_dashboard][Exit] Exported dashboard 3 to dashboard_export_20251220T203040.zip. +2025-12-20 23:30:40,746 - INFO - [save_and_unpack_dashboard][Enter] Processing dashboard. Unpack: False +2025-12-20 23:30:40,760 - INFO - [save_and_unpack_dashboard][State] Dashboard saved to: backups/SUPERSET/Misc Charts/dashboard_export_20251220T203040.zip +2025-12-20 23:30:40,761 - INFO - [archive_exports][Enter] Managing archive in backups/SUPERSET/Misc Charts +2025-12-20 23:30:40,762 - INFO - [export_dashboard][Enter] Exporting dashboard 2. +2025-12-20 23:30:40,928 - INFO - [export_dashboard][Exit] Exported dashboard 2 to dashboard_export_20251220T203040.zip. +2025-12-20 23:30:40,929 - INFO - [save_and_unpack_dashboard][Enter] Processing dashboard. Unpack: False +2025-12-20 23:30:40,930 - INFO - [save_and_unpack_dashboard][State] Dashboard saved to: backups/SUPERSET/USA Births Names/dashboard_export_20251220T203040.zip +2025-12-20 23:30:40,931 - INFO - [archive_exports][Enter] Managing archive in backups/SUPERSET/USA Births Names +2025-12-20 23:30:40,932 - INFO - [export_dashboard][Enter] Exporting dashboard 1. +2025-12-20 23:30:41,582 - INFO - [export_dashboard][Exit] Exported dashboard 1 to dashboard_export_20251220T203040.zip. +2025-12-20 23:30:41,582 - INFO - [save_and_unpack_dashboard][Enter] Processing dashboard. Unpack: False +2025-12-20 23:30:41,749 - INFO - [save_and_unpack_dashboard][State] Dashboard saved to: backups/SUPERSET/World Bank's Data/dashboard_export_20251220T203040.zip +2025-12-20 23:30:41,750 - INFO - [archive_exports][Enter] Managing archive in backups/SUPERSET/World Bank's Data +2025-12-20 23:30:41,752 - INFO - [consolidate_archive_folders][Enter] Consolidating archives in backups/SUPERSET +2025-12-20 23:30:41,753 - INFO - [remove_empty_directories][Enter] Starting cleanup of empty directories in backups/SUPERSET +2025-12-20 23:30:41,758 - INFO - [remove_empty_directories][Exit] Removed 0 empty directories. +2025-12-20 23:30:41,758 - INFO - [BackupPlugin][CoherenceCheck:Passed] Backup logic completed for superset. diff --git a/backend/backups/SUPERSET/COVID Vaccine Dashboard/dashboard_export_20251220T203038.zip b/backend/backups/SUPERSET/COVID Vaccine Dashboard/dashboard_export_20251220T203038.zip new file mode 100644 index 0000000..053eefe Binary files /dev/null and b/backend/backups/SUPERSET/COVID Vaccine Dashboard/dashboard_export_20251220T203038.zip differ diff --git a/backend/backups/SUPERSET/FCC New Coder Survey 2018/dashboard_export_20251220T203037.zip b/backend/backups/SUPERSET/FCC New Coder Survey 2018/dashboard_export_20251220T203037.zip new file mode 100644 index 0000000..9b37986 Binary files /dev/null and b/backend/backups/SUPERSET/FCC New Coder Survey 2018/dashboard_export_20251220T203037.zip differ diff --git a/backend/backups/SUPERSET/Featured Charts/dashboard_export_20251220T203039.zip b/backend/backups/SUPERSET/Featured Charts/dashboard_export_20251220T203039.zip new file mode 100644 index 0000000..f18a1e5 Binary files /dev/null and b/backend/backups/SUPERSET/Featured Charts/dashboard_export_20251220T203039.zip differ diff --git a/backend/backups/SUPERSET/Misc Charts/dashboard_export_20251220T203040.zip b/backend/backups/SUPERSET/Misc Charts/dashboard_export_20251220T203040.zip new file mode 100644 index 0000000..13589c1 Binary files /dev/null and b/backend/backups/SUPERSET/Misc Charts/dashboard_export_20251220T203040.zip differ diff --git a/backend/backups/SUPERSET/Sales Dashboard/dashboard_export_20251220T203038.zip b/backend/backups/SUPERSET/Sales Dashboard/dashboard_export_20251220T203038.zip new file mode 100644 index 0000000..817a978 Binary files /dev/null and b/backend/backups/SUPERSET/Sales Dashboard/dashboard_export_20251220T203038.zip differ diff --git a/backend/backups/SUPERSET/Slack Dashboard/dashboard_export_20251220T203039.zip b/backend/backups/SUPERSET/Slack Dashboard/dashboard_export_20251220T203039.zip new file mode 100644 index 0000000..478eda1 Binary files /dev/null and b/backend/backups/SUPERSET/Slack Dashboard/dashboard_export_20251220T203039.zip differ diff --git a/backend/backups/SUPERSET/USA Births Names/dashboard_export_20251220T203040.zip b/backend/backups/SUPERSET/USA Births Names/dashboard_export_20251220T203040.zip new file mode 100644 index 0000000..137ca32 Binary files /dev/null and b/backend/backups/SUPERSET/USA Births Names/dashboard_export_20251220T203040.zip differ diff --git a/backend/backups/SUPERSET/Unicode Test/dashboard_export_20251220T203038.zip b/backend/backups/SUPERSET/Unicode Test/dashboard_export_20251220T203038.zip new file mode 100644 index 0000000..f4764a5 Binary files /dev/null and b/backend/backups/SUPERSET/Unicode Test/dashboard_export_20251220T203038.zip differ diff --git a/backend/backups/SUPERSET/Video Game Sales/dashboard_export_20251220T203038.zip b/backend/backups/SUPERSET/Video Game Sales/dashboard_export_20251220T203038.zip new file mode 100644 index 0000000..4f6ce86 Binary files /dev/null and b/backend/backups/SUPERSET/Video Game Sales/dashboard_export_20251220T203038.zip differ diff --git a/backend/backups/SUPERSET/World Bank's Data/dashboard_export_20251220T203040.zip b/backend/backups/SUPERSET/World Bank's Data/dashboard_export_20251220T203040.zip new file mode 100644 index 0000000..9a83f8c Binary files /dev/null and b/backend/backups/SUPERSET/World Bank's Data/dashboard_export_20251220T203040.zip differ diff --git a/backend/backups/SUPERSET/deck.gl Demo/dashboard_export_20251220T203039.zip b/backend/backups/SUPERSET/deck.gl Demo/dashboard_export_20251220T203039.zip new file mode 100644 index 0000000..c07b2a5 Binary files /dev/null and b/backend/backups/SUPERSET/deck.gl Demo/dashboard_export_20251220T203039.zip differ diff --git a/backend/src/app.py b/backend/src/app.py index 9f54fc2..b1ef99e 100755 --- a/backend/src/app.py +++ b/backend/src/app.py @@ -42,9 +42,9 @@ app.add_middleware( # Include API routes -app.include_router(plugins.router, prefix="/plugins", tags=["Plugins"]) -app.include_router(tasks.router, prefix="/tasks", tags=["Tasks"]) -app.include_router(settings.router, prefix="/settings", tags=["Settings"]) +app.include_router(plugins.router, prefix="/api/plugins", tags=["Plugins"]) +app.include_router(tasks.router, prefix="/api/tasks", tags=["Tasks"]) +app.include_router(settings.router, prefix="/api/settings", tags=["Settings"]) # [DEF:WebSocketEndpoint:Endpoint] # @SEMANTICS: websocket, logs, streaming, real-time diff --git a/backend/tests/test_models.py b/backend/tests/test_models.py new file mode 100644 index 0000000..511fc27 --- /dev/null +++ b/backend/tests/test_models.py @@ -0,0 +1,49 @@ +import pytest +from superset_tool.models import SupersetConfig + +def test_superset_config_url_normalization(): + auth = { + "provider": "db", + "username": "admin", + "password": "password", + "refresh": "token" + } + + # Test with /api/v1 already present + config = SupersetConfig( + env="dev", + base_url="http://localhost:8088/api/v1", + auth=auth + ) + assert config.base_url == "http://localhost:8088/api/v1" + + # Test without /api/v1 + config = SupersetConfig( + env="dev", + base_url="http://localhost:8088", + auth=auth + ) + assert config.base_url == "http://localhost:8088/api/v1" + + # Test with trailing slash + config = SupersetConfig( + env="dev", + base_url="http://localhost:8088/", + auth=auth + ) + assert config.base_url == "http://localhost:8088/api/v1" + +def test_superset_config_invalid_url(): + auth = { + "provider": "db", + "username": "admin", + "password": "password", + "refresh": "token" + } + + with pytest.raises(ValueError, match="Must start with http:// or https://"): + SupersetConfig( + env="dev", + base_url="localhost:8088", + auth=auth + ) diff --git a/docs/settings.md b/docs/settings.md index 11a0cac..f539471 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -12,7 +12,7 @@ The settings mechanism allows users to configure multiple Superset environments Configuration is structured using Pydantic models in `backend/src/core/config_models.py`: -- `Environment`: Represents a Superset instance (URL, credentials). +- `Environment`: Represents a Superset instance (URL, credentials). The `base_url` is automatically normalized to include the `/api/v1` suffix if missing. - `GlobalSettings`: Global application parameters (e.g., `backup_path`). - `AppConfig`: The root configuration object. diff --git a/frontend/.svelte-kit/ambient.d.ts b/frontend/.svelte-kit/ambient.d.ts index 1396f51..743d147 100644 --- a/frontend/.svelte-kit/ambient.d.ts +++ b/frontend/.svelte-kit/ambient.d.ts @@ -27,20 +27,13 @@ */ declare module '$env/static/private' { export const LESSOPEN: string; - export const VSCODE_CWD: string; - export const VSCODE_ESM_ENTRYPOINT: string; export const USER: string; - export const VSCODE_NLS_CONFIG: string; export const npm_config_user_agent: string; - export const VSCODE_WSL_EXT_LOCATION: string; - export const VSCODE_HANDLES_UNCAUGHT_ERRORS: string; export const npm_node_execpath: string; export const SHLVL: string; export const npm_config_noproxy: string; export const HOME: string; export const OLDPWD: string; - export const VSCODE_RECONNECTION_GRACE_TIME: string; - export const VSCODE_IPC_HOOK_CLI: string; export const npm_package_json: string; export const PS1: string; export const npm_config_userconfig: string; @@ -49,11 +42,9 @@ declare module '$env/static/private' { export const WSL_DISTRO_NAME: string; export const COLOR: string; export const WAYLAND_DISPLAY: string; - export const VSCODE_L10N_BUNDLE_LOCATION: string; export const LOGNAME: string; export const NAME: string; export const WSL_INTEROP: string; - export const VSCODE_HANDLES_SIGPIPE: string; export const PULSE_SERVER: string; export const _: string; export const npm_config_prefix: string; @@ -73,15 +64,12 @@ declare module '$env/static/private' { export const SHELL: string; export const npm_package_version: string; export const npm_lifecycle_event: string; - export const ELECTRON_RUN_AS_NODE: string; - export const KILOCODE_POSTHOG_API_KEY: string; export const GOOGLE_CLOUD_PROJECT: string; export const LESSCLOSE: string; export const VIRTUAL_ENV: string; export const npm_config_globalconfig: string; export const npm_config_init_module: string; export const PWD: string; - export const LC_ALL: string; export const npm_execpath: string; export const XDG_DATA_DIRS: string; export const npm_config_global_prefix: string; @@ -104,7 +92,7 @@ declare module '$env/static/private' { * ``` */ declare module '$env/static/public' { - + export const PUBLIC_WS_URL: string; } /** @@ -122,20 +110,13 @@ declare module '$env/static/public' { declare module '$env/dynamic/private' { export const env: { LESSOPEN: string; - VSCODE_CWD: string; - VSCODE_ESM_ENTRYPOINT: string; USER: string; - VSCODE_NLS_CONFIG: string; npm_config_user_agent: string; - VSCODE_WSL_EXT_LOCATION: string; - VSCODE_HANDLES_UNCAUGHT_ERRORS: string; npm_node_execpath: string; SHLVL: string; npm_config_noproxy: string; HOME: string; OLDPWD: string; - VSCODE_RECONNECTION_GRACE_TIME: string; - VSCODE_IPC_HOOK_CLI: string; npm_package_json: string; PS1: string; npm_config_userconfig: string; @@ -144,11 +125,9 @@ declare module '$env/dynamic/private' { WSL_DISTRO_NAME: string; COLOR: string; WAYLAND_DISPLAY: string; - VSCODE_L10N_BUNDLE_LOCATION: string; LOGNAME: string; NAME: string; WSL_INTEROP: string; - VSCODE_HANDLES_SIGPIPE: string; PULSE_SERVER: string; _: string; npm_config_prefix: string; @@ -168,15 +147,12 @@ declare module '$env/dynamic/private' { SHELL: string; npm_package_version: string; npm_lifecycle_event: string; - ELECTRON_RUN_AS_NODE: string; - KILOCODE_POSTHOG_API_KEY: string; GOOGLE_CLOUD_PROJECT: string; LESSCLOSE: string; VIRTUAL_ENV: string; npm_config_globalconfig: string; npm_config_init_module: string; PWD: string; - LC_ALL: string; npm_execpath: string; XDG_DATA_DIRS: string; npm_config_global_prefix: string; @@ -204,6 +180,7 @@ declare module '$env/dynamic/private' { */ declare module '$env/dynamic/public' { export const env: { + PUBLIC_WS_URL: string; [key: `PUBLIC_${string}`]: string | undefined; } } diff --git a/frontend/.svelte-kit/generated/server/internal.js b/frontend/.svelte-kit/generated/server/internal.js index 531bf75..5c177c9 100644 --- a/frontend/.svelte-kit/generated/server/internal.js +++ b/frontend/.svelte-kit/generated/server/internal.js @@ -24,7 +24,7 @@ export const options = { app: ({ head, body, assets, nonce, env }) => "\n\n\t\n\t\t\n\t\t\n\t\t\n\t\t" + head + "\n\t\n\t\n\t\t
" + body + "
\n\t\n\n", error: ({ status, message }) => "\n\n\t\n\t\t\n\t\t" + message + "\n\n\t\t\n\t\n\t\n\t\t
\n\t\t\t" + status + "\n\t\t\t
\n\t\t\t\t

" + message + "

\n\t\t\t
\n\t\t
\n\t\n\n" }, - version_hash: "1ynwnul" + version_hash: "cx7alu" }; export async function get_hooks() { diff --git a/frontend/.svelte-kit/output/client/.vite/manifest.json b/frontend/.svelte-kit/output/client/.vite/manifest.json index 3bad808..365e460 100644 --- a/frontend/.svelte-kit/output/client/.vite/manifest.json +++ b/frontend/.svelte-kit/output/client/.vite/manifest.json @@ -1,14 +1,14 @@ { ".svelte-kit/generated/client-optimized/app.js": { - "file": "_app/immutable/entry/app.B-xBk5-0.js", + "file": "_app/immutable/entry/app.BXnpILpp.js", "name": "entry/app", "src": ".svelte-kit/generated/client-optimized/app.js", "isEntry": true, "imports": [ - "_CQO205-B.js", - "_CWb4Vnhz.js", - "_CqZim_6h.js", - "_C98uKxzC.js" + "_BtL0wB3H.js", + "_cv2LK44M.js", + "_BxZpmA7Z.js", + "_vVxDbqKK.js" ], "dynamicImports": [ ".svelte-kit/generated/client-optimized/nodes/0.js", @@ -18,142 +18,145 @@ ] }, ".svelte-kit/generated/client-optimized/nodes/0.js": { - "file": "_app/immutable/nodes/0.Cd4CVt-Z.js", + "file": "_app/immutable/nodes/0.DZdF_zz-.js", "name": "nodes/0", "src": ".svelte-kit/generated/client-optimized/nodes/0.js", "isEntry": true, "isDynamicEntry": true, "imports": [ - "_CWb4Vnhz.js", - "_CCsGeFPC.js", - "_CQO205-B.js", - "_DKg_yD9X.js", - "_BEiADdeo.js", - "_CsANhQOh.js" + "_cv2LK44M.js", + "_CRLlKr96.js", + "_BtL0wB3H.js", + "_xdjHc-A2.js", + "_DXE57cnx.js", + "_Dbod7Wv8.js" + ], + "css": [ + "_app/immutable/assets/0.RZHRvmcL.css" ] }, ".svelte-kit/generated/client-optimized/nodes/1.js": { - "file": "_app/immutable/nodes/1.CppBCq8O.js", + "file": "_app/immutable/nodes/1.Bh-fCbID.js", "name": "nodes/1", "src": ".svelte-kit/generated/client-optimized/nodes/1.js", "isEntry": true, "isDynamicEntry": true, "imports": [ - "_CWb4Vnhz.js", - "_CCsGeFPC.js", - "_CQO205-B.js", - "_BEiADdeo.js" + "_cv2LK44M.js", + "_CRLlKr96.js", + "_BtL0wB3H.js", + "_DXE57cnx.js" ] }, ".svelte-kit/generated/client-optimized/nodes/2.js": { - "file": "_app/immutable/nodes/2.DbjHrap6.js", + "file": "_app/immutable/nodes/2.BmiXdPHI.js", "name": "nodes/2", "src": ".svelte-kit/generated/client-optimized/nodes/2.js", "isEntry": true, "isDynamicEntry": true, "imports": [ - "_BGnnHgKo.js", - "_CWb4Vnhz.js", - "_CCsGeFPC.js", - "_CQO205-B.js", - "_C98uKxzC.js", - "_CsANhQOh.js", - "_CqZim_6h.js", - "_DKg_yD9X.js" + "_DyPeVqDG.js", + "_cv2LK44M.js", + "_CRLlKr96.js", + "_BtL0wB3H.js", + "_vVxDbqKK.js", + "_Dbod7Wv8.js", + "_BxZpmA7Z.js", + "_xdjHc-A2.js" ] }, ".svelte-kit/generated/client-optimized/nodes/3.js": { - "file": "_app/immutable/nodes/3.BgpIj6zk.js", + "file": "_app/immutable/nodes/3.guWMyWpk.js", "name": "nodes/3", "src": ".svelte-kit/generated/client-optimized/nodes/3.js", "isEntry": true, "isDynamicEntry": true, "imports": [ - "_BGnnHgKo.js", - "_CWb4Vnhz.js", - "_CCsGeFPC.js", - "_CQO205-B.js", - "_C98uKxzC.js", - "_CsANhQOh.js" + "_DyPeVqDG.js", + "_cv2LK44M.js", + "_CRLlKr96.js", + "_BtL0wB3H.js", + "_vVxDbqKK.js", + "_Dbod7Wv8.js" ] }, - "_BEiADdeo.js": { - "file": "_app/immutable/chunks/BEiADdeo.js", - "name": "stores", - "imports": [ - "_CHnJS4Dz.js" - ] - }, - "_BGnnHgKo.js": { - "file": "_app/immutable/chunks/BGnnHgKo.js", - "name": "api", - "imports": [ - "_CQO205-B.js", - "_CsANhQOh.js" - ] - }, - "_C98uKxzC.js": { - "file": "_app/immutable/chunks/C98uKxzC.js", - "name": "props", - "imports": [ - "_CQO205-B.js", - "_CWb4Vnhz.js" - ] - }, - "_CCsGeFPC.js": { - "file": "_app/immutable/chunks/CCsGeFPC.js", - "name": "legacy", - "imports": [ - "_CQO205-B.js" - ] - }, - "_CHnJS4Dz.js": { - "file": "_app/immutable/chunks/CHnJS4Dz.js", - "name": "entry", - "imports": [ - "_CQO205-B.js", - "_CqZim_6h.js" - ] - }, - "_CQO205-B.js": { - "file": "_app/immutable/chunks/CQO205-B.js", + "_BtL0wB3H.js": { + "file": "_app/immutable/chunks/BtL0wB3H.js", "name": "index" }, - "_CWb4Vnhz.js": { - "file": "_app/immutable/chunks/CWb4Vnhz.js", - "name": "disclose-version", - "imports": [ - "_CQO205-B.js" - ] - }, - "_CqZim_6h.js": { - "file": "_app/immutable/chunks/CqZim_6h.js", + "_BxZpmA7Z.js": { + "file": "_app/immutable/chunks/BxZpmA7Z.js", "name": "index-client", "imports": [ - "_CQO205-B.js" + "_BtL0wB3H.js" ] }, - "_CsANhQOh.js": { - "file": "_app/immutable/chunks/CsANhQOh.js", + "_CRLlKr96.js": { + "file": "_app/immutable/chunks/CRLlKr96.js", + "name": "legacy", + "imports": [ + "_BtL0wB3H.js" + ] + }, + "_D0iaTcAo.js": { + "file": "_app/immutable/chunks/D0iaTcAo.js", + "name": "entry", + "imports": [ + "_BtL0wB3H.js", + "_BxZpmA7Z.js" + ] + }, + "_DXE57cnx.js": { + "file": "_app/immutable/chunks/DXE57cnx.js", + "name": "stores", + "imports": [ + "_D0iaTcAo.js" + ] + }, + "_Dbod7Wv8.js": { + "file": "_app/immutable/chunks/Dbod7Wv8.js", "name": "toasts", "imports": [ - "_CQO205-B.js" + "_BtL0wB3H.js" ] }, - "_DKg_yD9X.js": { - "file": "_app/immutable/chunks/DKg_yD9X.js", + "_DyPeVqDG.js": { + "file": "_app/immutable/chunks/DyPeVqDG.js", + "name": "api", + "imports": [ + "_BtL0wB3H.js", + "_Dbod7Wv8.js" + ] + }, + "_cv2LK44M.js": { + "file": "_app/immutable/chunks/cv2LK44M.js", + "name": "disclose-version", + "imports": [ + "_BtL0wB3H.js" + ] + }, + "_vVxDbqKK.js": { + "file": "_app/immutable/chunks/vVxDbqKK.js", + "name": "props", + "imports": [ + "_BtL0wB3H.js", + "_cv2LK44M.js" + ] + }, + "_xdjHc-A2.js": { + "file": "_app/immutable/chunks/xdjHc-A2.js", "name": "class", "imports": [ - "_CQO205-B.js" + "_BtL0wB3H.js" ] }, "node_modules/@sveltejs/kit/src/runtime/client/entry.js": { - "file": "_app/immutable/entry/start.CiUb2lZD.js", + "file": "_app/immutable/entry/start.BHAeOrfR.js", "name": "entry/start", "src": "node_modules/@sveltejs/kit/src/runtime/client/entry.js", "isEntry": true, "imports": [ - "_CHnJS4Dz.js" + "_D0iaTcAo.js" ] } } \ No newline at end of file diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/BEiADdeo.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/BEiADdeo.js deleted file mode 100644 index f2c067c..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/chunks/BEiADdeo.js +++ /dev/null @@ -1 +0,0 @@ -import{s as e}from"./CHnJS4Dz.js";const r=()=>{const s=e;return{page:{subscribe:s.page.subscribe},navigating:{subscribe:s.navigating.subscribe},updated:s.updated}},b={subscribe(s){return r().page.subscribe(s)}};export{b as p}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/BGnnHgKo.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/BGnnHgKo.js deleted file mode 100644 index f0e6762..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/chunks/BGnnHgKo.js +++ /dev/null @@ -1 +0,0 @@ -import{h as v,Z as S,a5 as T,a6 as b,a7 as C,a8 as P,a9 as I,aa as w,ab as N,e as $,ac as p,J as i,ad as L}from"./CQO205-B.js";import{a as m}from"./CsANhQOh.js";const M=Symbol("is custom element"),q=Symbol("is html");function F(e){if(v){var t=!1,r=()=>{if(!t){if(t=!0,e.hasAttribute("value")){var s=e.value;k(e,"value",null),e.value=s}if(e.hasAttribute("checked")){var a=e.checked;k(e,"checked",null),e.checked=a}}};e.__on_r=r,S(r),T()}}function k(e,t,r,s){var a=j(e);v&&(a[t]=e.getAttribute(t),t==="src"||t==="srcset"||t==="href"&&e.nodeName==="LINK")||a[t]!==(a[t]=r)&&(t==="loading"&&(e[b]=r),r==null?e.removeAttribute(t):typeof r!="string"&&O(e).includes(t)?e[t]=r:e.setAttribute(t,r))}function j(e){return e.__attributes??={[M]:e.nodeName.includes("-"),[q]:e.namespaceURI===C}}var y=new Map;function O(e){var t=e.getAttribute("is")||e.nodeName,r=y.get(t);if(r)return r;y.set(t,r=[]);for(var s,a=e,o=Element.prototype;o!==a;){s=I(a);for(var n in s)s[n].set&&r.push(n);a=P(a)}return r}function U(e,t,r=t){var s=new WeakSet;w(e,"input",async a=>{var o=a?e.defaultValue:e.value;if(o=u(e)?h(o):o,r(o),i!==null&&s.add(i),await N(),o!==(o=t())){var n=e.selectionStart,f=e.selectionEnd,A=e.value.length;if(e.value=o??"",f!==null){var d=e.value.length;n===f&&f===A&&d>A?(e.selectionStart=d,e.selectionEnd=d):(e.selectionStart=n,e.selectionEnd=Math.min(f,d))}}}),(v&&e.defaultValue!==e.value||$(t)==null&&e.value)&&(r(u(e)?h(e.value):e.value),i!==null&&s.add(i)),p(()=>{var a=t();if(e===document.activeElement){var o=L??i;if(s.has(o))return}u(e)&&a===h(e.value)||e.type==="date"&&!a&&!e.value||a!==e.value&&(e.value=a??"")})}function B(e,t,r=t){w(e,"change",s=>{var a=s?e.defaultChecked:e.checked;r(a)}),(v&&e.defaultChecked!==e.checked||$(t)==null)&&r(e.checked),p(()=>{var s=t();e.checked=!!s})}function u(e){var t=e.type;return t==="number"||t==="range"}function h(e){return e===""?null:+e}const E="/api";async function c(e){try{console.log(`[api.fetchApi][Action] Fetching from context={{'endpoint': '${e}'}}`);const t=await fetch(`${E}${e}`);if(!t.ok)throw new Error(`API request failed with status ${t.status}`);return await t.json()}catch(t){throw console.error(`[api.fetchApi][Coherence:Failed] Error fetching from ${e}:`,t),m(t.message,"error"),t}}async function _(e,t){try{console.log(`[api.postApi][Action] Posting to context={{'endpoint': '${e}'}}`);const r=await fetch(`${E}${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!r.ok)throw new Error(`API request failed with status ${r.status}`);return await r.json()}catch(r){throw console.error(`[api.postApi][Coherence:Failed] Error posting to ${e}:`,r),m(r.message,"error"),r}}async function g(e,t="GET",r=null){try{console.log(`[api.requestApi][Action] ${t} to context={{'endpoint': '${e}'}}`);const s={method:t,headers:{"Content-Type":"application/json"}};r&&(s.body=JSON.stringify(r));const a=await fetch(`${E}${e}`,s);if(!a.ok){const o=await a.json().catch(()=>({}));throw new Error(o.detail||`API request failed with status ${a.status}`)}return await a.json()}catch(s){throw console.error(`[api.requestApi][Coherence:Failed] Error ${t} to ${e}:`,s),m(s.message,"error"),s}}const l={getPlugins:()=>c("/plugins/"),getTasks:()=>c("/tasks/"),getTask:e=>c(`/tasks/${e}`),createTask:(e,t)=>_("/tasks/",{plugin_id:e,params:t}),getSettings:()=>c("/settings/"),updateGlobalSettings:e=>g("/settings/global","PATCH",e),getEnvironments:()=>c("/settings/environments"),addEnvironment:e=>_("/settings/environments",e),updateEnvironment:(e,t)=>g(`/settings/environments/${e}`,"PUT",t),deleteEnvironment:e=>g(`/settings/environments/${e}`,"DELETE"),testEnvironmentConnection:e=>_(`/settings/environments/${e}/test`,{})},D=l.updateGlobalSettings,H=l.addEnvironment,J=l.updateEnvironment,R=l.deleteEnvironment,V=l.testEnvironmentConnection;export{l as a,U as b,B as c,J as d,H as e,R as f,F as r,k as s,V as t,D as u}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/C98uKxzC.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/C98uKxzC.js deleted file mode 100644 index 06fea01..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/chunks/C98uKxzC.js +++ /dev/null @@ -1 +0,0 @@ -import{J as E,S as y,X as S,T as L,v as P,L as T,h as g,E as M,ae as k,M as w,w as B,z as N,af as x,B as Y,H as C,C as F,x as U,D as R,ag as j,ah as q,j as b,ai as z,o as H,aj as $,ak as G,A as J,d as X,al as Z,am as K,an as Q,ao as V,ap as W,a3 as ee,e as te,aq as ae,ar as se,as as re}from"./CQO205-B.js";import{d as ie}from"./CWb4Vnhz.js";class ne{anchor;#t=new Map;#a=new Map;#e=new Map;#s=new Set;#r=!0;constructor(e,a=!0){this.anchor=e,this.#r=a}#i=()=>{var e=E;if(this.#t.has(e)){var a=this.#t.get(e),t=this.#a.get(a);if(t)y(t),this.#s.delete(a);else{var n=this.#e.get(a);n&&(this.#a.set(a,n.effect),this.#e.delete(a),n.fragment.lastChild.remove(),this.anchor.before(n.fragment),t=n.effect)}for(const[s,i]of this.#t){if(this.#t.delete(s),s===e)break;const r=this.#e.get(i);r&&(S(r.effect),this.#e.delete(i))}for(const[s,i]of this.#a){if(s===a||this.#s.has(s))continue;const r=()=>{if(Array.from(this.#t.values()).includes(s)){var h=document.createDocumentFragment();k(i,h),h.append(P()),this.#e.set(s,{effect:i,fragment:h})}else S(i);this.#s.delete(s),this.#a.delete(s)};this.#r||!t?(this.#s.add(s),L(i,r,!1)):r()}}};#n=e=>{this.#t.delete(e);const a=Array.from(this.#t.values());for(const[t,n]of this.#e)a.includes(t)||(S(n.effect),this.#e.delete(t))};ensure(e,a){var t=E,n=w();if(a&&!this.#a.has(e)&&!this.#e.has(e))if(n){var s=document.createDocumentFragment(),i=P();s.append(i),this.#e.set(e,{effect:T(()=>a(i)),fragment:s})}else this.#a.set(e,T(()=>a(this.anchor)));if(this.#t.set(t,e),n){for(const[r,f]of this.#a)r===e?t.skipped_effects.delete(f):t.skipped_effects.add(f);for(const[r,f]of this.#e)r===e?t.skipped_effects.delete(f.effect):t.skipped_effects.add(f.effect);t.oncommit(this.#i),t.ondiscard(this.#n)}else g&&(this.anchor=M),this.#i()}}function de(d,e,a=!1){g&&N();var t=new ne(d),n=a?x:0;function s(i,r){if(g){const h=Y(d)===C;if(i===h){var f=F();U(f),t.anchor=f,R(!1),t.ensure(i,r),R(!0);return}}t.ensure(i,r)}B(()=>{var i=!1;e((r,f=!0)=>{i=!0,s(f,r)}),i||s(!1,null)},n)}function he(d,e,a,t){var n=!X||(a&Z)!==0,s=(a&K)!==0,i=(a&re)!==0,r=t,f=!0,h=()=>(f&&(f=!1,r=i?te(t):t),r),o;if(s){var I=V in d||W in d;o=j(d,e)?.set??(I&&e in d?c=>d[e]=c:void 0)}var _,p=!1;s?[_,p]=ie(()=>d[e]):_=d[e],_===void 0&&t!==void 0&&(_=h(),o&&(n&&ae(),o(_)));var u;if(n?u=()=>{var c=d[e];return c===void 0?h():(f=!0,c)}:u=()=>{var c=d[e];return c!==void 0&&(r=void 0),c===void 0?r:c},n&&(a&q)===0)return u;if(o){var D=d.$$legacy;return(function(c,v){return arguments.length>0?((!n||!v||D||p)&&o(v?u():c),c):u()})}var m=!1,l=((a&se)!==0?ee:J)(()=>(m=!1,u()));s&&b(l);var O=$;return(function(c,v){if(arguments.length>0){const A=v?b(l):n&&s?z(c):c;return H(l,A),m=!0,r!==void 0&&(r=A),c}return Q&&m||(O.f&G)!==0?l.v:b(l)})}export{ne as B,de as i,he as p}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CCsGeFPC.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/CCsGeFPC.js deleted file mode 100644 index e040cf5..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CCsGeFPC.js +++ /dev/null @@ -1 +0,0 @@ -import{b as d,a0 as g,u as c,e as b,a1 as i,a2 as m,j as p,k,a3 as v,a4 as h}from"./CQO205-B.js";function x(a=!1){const s=d,e=s.l.u;if(!e)return;let f=()=>k(s.s);if(a){let n=0,t={};const _=v(()=>{let l=!1;const r=s.s;for(const o in r)r[o]!==t[o]&&(t[o]=r[o],l=!0);return l&&n++,n});f=()=>p(_)}e.b.length&&g(()=>{u(s,f),i(e.b)}),c(()=>{const n=b(()=>e.m.map(m));return()=>{for(const t of n)typeof t=="function"&&t()}}),e.a.length&&c(()=>{u(s,f),i(e.a)})}function u(a,s){if(a.l.s)for(const e of a.l.s)p(e);s()}h();export{x as i}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CHnJS4Dz.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/CHnJS4Dz.js deleted file mode 100644 index 5fb6da7..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CHnJS4Dz.js +++ /dev/null @@ -1 +0,0 @@ -import{$ as be,aA as U,j as T,o as P,ab as Z,b1 as Ne,b2 as mt}from"./CQO205-B.js";import{o as qe}from"./CqZim_6h.js";class ke{constructor(t,n){this.status=t,typeof n=="string"?this.body={message:n}:n?this.body=n:this.body={message:`Error: ${t}`}}toString(){return JSON.stringify(this.body)}}class Ee{constructor(t,n){this.status=t,this.location=n}}class Se extends Error{constructor(t,n,a){super(a),this.status=t,this.text=n}}new URL("sveltekit-internal://");function _t(e,t){return e==="/"||t==="ignore"?e:t==="never"?e.endsWith("/")?e.slice(0,-1):e:t==="always"&&!e.endsWith("/")?e+"/":e}function wt(e){return e.split("%25").map(decodeURI).join("%25")}function vt(e){for(const t in e)e[t]=decodeURIComponent(e[t]);return e}function de({href:e}){return e.split("#")[0]}function yt(e,t,n,a=!1){const r=new URL(e);Object.defineProperty(r,"searchParams",{value:new Proxy(r.searchParams,{get(o,s){if(s==="get"||s==="getAll"||s==="has")return l=>(n(l),o[s](l));t();const c=Reflect.get(o,s);return typeof c=="function"?c.bind(o):c}}),enumerable:!0,configurable:!0});const i=["href","pathname","search","toString","toJSON"];a&&i.push("hash");for(const o of i)Object.defineProperty(r,o,{get(){return t(),e[o]},enumerable:!0,configurable:!0});return r}function bt(...e){let t=5381;for(const n of e)if(typeof n=="string"){let a=n.length;for(;a;)t=t*33^n.charCodeAt(--a)}else if(ArrayBuffer.isView(n)){const a=new Uint8Array(n.buffer,n.byteOffset,n.byteLength);let r=a.length;for(;r;)t=t*33^a[--r]}else throw new TypeError("value must be a string or TypedArray");return(t>>>0).toString(36)}new TextEncoder;new TextDecoder;function kt(e){const t=atob(e),n=new Uint8Array(t.length);for(let a=0;a((e instanceof Request?e.method:t?.method||"GET")!=="GET"&&G.delete(Re(e)),Et(e,t));const G=new Map;function St(e,t){const n=Re(e,t),a=document.querySelector(n);if(a?.textContent){a.remove();let{body:r,...i}=JSON.parse(a.textContent);const o=a.getAttribute("data-ttl");return o&&G.set(n,{body:r,init:i,ttl:1e3*Number(o)}),a.getAttribute("data-b64")!==null&&(r=kt(r)),Promise.resolve(new Response(r,i))}return window.fetch(e,t)}function Rt(e,t,n){if(G.size>0){const a=Re(e,n),r=G.get(a);if(r){if(performance.now(){const r=/^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(a);if(r)return t.push({name:r[1],matcher:r[2],optional:!1,rest:!0,chained:!0}),"(?:/([^]*))?";const i=/^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(a);if(i)return t.push({name:i[1],matcher:i[2],optional:!0,rest:!1,chained:!0}),"(?:/([^/]+))?";if(!a)return;const o=a.split(/\[(.+?)\](?!\])/);return"/"+o.map((c,l)=>{if(l%2){if(c.startsWith("x+"))return he(String.fromCharCode(parseInt(c.slice(2),16)));if(c.startsWith("u+"))return he(String.fromCharCode(...c.slice(2).split("-").map(w=>parseInt(w,16))));const d=xt.exec(c),[,h,f,u,p]=d;return t.push({name:u,matcher:p,optional:!!h,rest:!!f,chained:f?l===1&&o[0]==="":!1}),f?"([^]*?)":h?"([^/]*)?":"([^/]+?)"}return he(c)}).join("")}).join("")}/?$`),params:t}}function Lt(e){return e!==""&&!/^\([^)]+\)$/.test(e)}function Ut(e){return e.slice(1).split("/").filter(Lt)}function Tt(e,t,n){const a={},r=e.slice(1),i=r.filter(s=>s!==void 0);let o=0;for(let s=0;sd).join("/"),o=0),l===void 0){c.rest&&(a[c.name]="");continue}if(!c.matcher||n[c.matcher](l)){a[c.name]=l;const d=t[s+1],h=r[s+1];d&&!d.rest&&d.optional&&h&&c.chained&&(o=0),!d&&!h&&Object.keys(a).length===i.length&&(o=0);continue}if(c.optional&&c.chained){o++;continue}return}if(!o)return a}function he(e){return e.normalize().replace(/[[\]]/g,"\\$&").replace(/%/g,"%25").replace(/\//g,"%2[Ff]").replace(/\?/g,"%3[Ff]").replace(/#/g,"%23").replace(/[.*+?^${}()|\\]/g,"\\$&")}function Pt({nodes:e,server_loads:t,dictionary:n,matchers:a}){const r=new Set(t);return Object.entries(n).map(([s,[c,l,d]])=>{const{pattern:h,params:f}=At(s),u={id:s,exec:p=>{const w=h.exec(p);if(w)return Tt(w,f,a)},errors:[1,...d||[]].map(p=>e[p]),layouts:[0,...l||[]].map(o),leaf:i(c)};return u.errors.length=u.layouts.length=Math.max(u.errors.length,u.layouts.length),u});function i(s){const c=s<0;return c&&(s=~s),[c,e[s]]}function o(s){return s===void 0?s:[r.has(s),e[s]]}}function We(e,t=JSON.parse){try{return t(sessionStorage[e])}catch{}}function De(e,t,n=JSON.stringify){const a=n(t);try{sessionStorage[e]=a}catch{}}const A=globalThis.__sveltekit_1uq6ubj?.base??"",It=globalThis.__sveltekit_1uq6ubj?.assets??A??"",Ot="1766259433446",Ye="sveltekit:snapshot",Je="sveltekit:scroll",ze="sveltekit:states",$t="sveltekit:pageurl",B="sveltekit:history",H="sveltekit:navigation",j={tap:1,hover:2,viewport:3,eager:4,off:-1,false:-1},xe=location.origin;function Xe(e){if(e instanceof URL)return e;let t=document.baseURI;if(!t){const n=document.getElementsByTagName("base");t=n.length?n[0].href:document.URL}return new URL(e,t)}function ce(){return{x:pageXOffset,y:pageYOffset}}function V(e,t){return e.getAttribute(`data-sveltekit-${t}`)}const Ve={...j,"":j.hover};function Qe(e){let t=e.assignedSlot??e.parentNode;return t?.nodeType===11&&(t=t.host),t}function Ze(e,t){for(;e&&e!==t;){if(e.nodeName.toUpperCase()==="A"&&e.hasAttribute("href"))return e;e=Qe(e)}}function me(e,t,n){let a;try{if(a=new URL(e instanceof SVGAElement?e.href.baseVal:e.href,document.baseURI),n&&a.hash.match(/^#[^/]/)){const s=location.hash.split("#")[1]||"/";a.hash=`#${s}${a.hash}`}}catch{}const r=e instanceof SVGAElement?e.target.baseVal:e.target,i=!a||!!r||le(a,t,n)||(e.getAttribute("rel")||"").split(/\s+/).includes("external"),o=a?.origin===xe&&e.hasAttribute("download");return{url:a,external:i,target:r,download:o}}function ee(e){let t=null,n=null,a=null,r=null,i=null,o=null,s=e;for(;s&&s!==document.documentElement;)a===null&&(a=V(s,"preload-code")),r===null&&(r=V(s,"preload-data")),t===null&&(t=V(s,"keepfocus")),n===null&&(n=V(s,"noscroll")),i===null&&(i=V(s,"reload")),o===null&&(o=V(s,"replacestate")),s=Qe(s);function c(l){switch(l){case"":case"true":return!0;case"off":case"false":return!1;default:return}}return{preload_code:Ve[a??"off"],preload_data:Ve[r??"off"],keepfocus:c(t),noscroll:c(n),reload:c(i),replace_state:c(o)}}function Be(e){const t=be(e);let n=!0;function a(){n=!0,t.update(o=>o)}function r(o){n=!1,t.set(o)}function i(o){let s;return t.subscribe(c=>{(s===void 0||n&&c!==s)&&o(s=c)})}return{notify:a,set:r,subscribe:i}}const et={v:()=>{}};function Ct(){const{set:e,subscribe:t}=be(!1);let n;async function a(){clearTimeout(n);try{const r=await fetch(`${It}/_app/version.json`,{headers:{pragma:"no-cache","cache-control":"no-cache"}});if(!r.ok)return!1;const o=(await r.json()).version!==Ot;return o&&(e(!0),et.v(),clearTimeout(n)),o}catch{return!1}}return{subscribe:t,check:a}}function le(e,t,n){return e.origin!==xe||!e.pathname.startsWith(t)?!0:n?e.pathname!==location.pathname:!1}function ln(e){}const tt=new Set(["load","prerender","csr","ssr","trailingSlash","config"]);[...tt];const jt=new Set([...tt]);[...jt];function Nt(e){return e.filter(t=>t!=null)}function Ae(e){return e instanceof ke||e instanceof Se?e.status:500}function qt(e){return e instanceof Se?e.text:"Internal Error"}let k,W,pe;const Dt=qe.toString().includes("$$")||/function \w+\(\) \{\}/.test(qe.toString());Dt?(k={data:{},form:null,error:null,params:{},route:{id:null},state:{},status:-1,url:new URL("https://example.com")},W={current:null},pe={current:!1}):(k=new class{#e=U({});get data(){return T(this.#e)}set data(t){P(this.#e,t)}#t=U(null);get form(){return T(this.#t)}set form(t){P(this.#t,t)}#n=U(null);get error(){return T(this.#n)}set error(t){P(this.#n,t)}#a=U({});get params(){return T(this.#a)}set params(t){P(this.#a,t)}#r=U({id:null});get route(){return T(this.#r)}set route(t){P(this.#r,t)}#o=U({});get state(){return T(this.#o)}set state(t){P(this.#o,t)}#s=U(-1);get status(){return T(this.#s)}set status(t){P(this.#s,t)}#i=U(new URL("https://example.com"));get url(){return T(this.#i)}set url(t){P(this.#i,t)}},W=new class{#e=U(null);get current(){return T(this.#e)}set current(t){P(this.#e,t)}},pe=new class{#e=U(!1);get current(){return T(this.#e)}set current(t){P(this.#e,t)}},et.v=()=>pe.current=!0);function nt(e){Object.assign(k,e)}const Ke={spanContext(){return Vt},setAttribute(){return this},setAttributes(){return this},addEvent(){return this},setStatus(){return this},updateName(){return this},end(){return this},isRecording(){return!1},recordException(){return this},addLink(){return this},addLinks(){return this}},Vt={traceId:"",spanId:"",traceFlags:0},Bt=new Set(["icon","shortcut icon","apple-touch-icon"]),q=We(Je)??{},Y=We(Ye)??{},C={url:Be({}),page:Be({}),navigating:be(null),updated:Ct()};function Le(e){q[e]=ce()}function Kt(e,t){let n=e+1;for(;q[n];)delete q[n],n+=1;for(n=t+1;Y[n];)delete Y[n],n+=1}function J(e,t=!1){return t?location.replace(e.href):location.href=e.href,new Promise(()=>{})}async function at(){if("serviceWorker"in navigator){const e=await navigator.serviceWorker.getRegistration(A||"/");e&&await e.update()}}function Fe(){}let Ue,_e,te,I,we,v;const ne=[],ae=[];let R=null;function ve(){R?.fork?.then(e=>e?.discard()),R=null}const Q=new Map,rt=new Set,Ft=new Set,M=new Set;let _={branch:[],error:null,url:null},ot=!1,re=!1,Ge=!0,z=!1,F=!1,st=!1,Te=!1,Pe,y,x,N;const oe=new Set,Me=new Map;async function hn(e,t,n){globalThis.__sveltekit_1uq6ubj?.data&&globalThis.__sveltekit_1uq6ubj.data,document.URL!==location.href&&(location.href=location.href),v=e,await e.hooks.init?.(),Ue=Pt(e),I=document.documentElement,we=t,_e=e.nodes[0],te=e.nodes[1],_e(),te(),y=history.state?.[B],x=history.state?.[H],y||(y=x=Date.now(),history.replaceState({...history.state,[B]:y,[H]:x},""));const a=q[y];function r(){a&&(history.scrollRestoration="manual",scrollTo(a.x,a.y))}n?(r(),await nn(we,n)):(await K({type:"enter",url:Xe(v.hash?on(new URL(location.href)):location.href),replace_state:!0}),r()),tn()}function Gt(){ne.length=0,Te=!1}function it(e){ae.some(t=>t?.snapshot)&&(Y[e]=ae.map(t=>t?.snapshot?.capture()))}function ct(e){Y[e]?.forEach((t,n)=>{ae[n]?.snapshot?.restore(t)})}function He(){Le(y),De(Je,q),it(x),De(Ye,Y)}async function Mt(e,t,n,a){let r;t.invalidateAll&&ve(),await K({type:"goto",url:Xe(e),keepfocus:t.keepFocus,noscroll:t.noScroll,replace_state:t.replaceState,state:t.state,redirect_count:n,nav_token:a,accept:()=>{t.invalidateAll&&(Te=!0,r=[...Me.keys()]),t.invalidate&&t.invalidate.forEach(en)}}),t.invalidateAll&&Z().then(Z).then(()=>{Me.forEach(({resource:i},o)=>{r?.includes(o)&&i.refresh?.()})})}async function Ht(e){if(e.id!==R?.id){ve();const t={};if(oe.add(t),R={id:e.id,token:t,promise:ft({...e,preload:t}).then(n=>(oe.delete(t),n.type==="loaded"&&n.state.error&&ve(),n)),fork:null},Ne){const n=R;n.fork=n.promise.then(a=>{if(n===R&&a.type==="loaded")try{return Ne(()=>{Pe.$set(a.props),nt(a.props.page)})}catch{}return null})}}return R.promise}async function ge(e){const t=(await ue(e,!1))?.route;t&&await Promise.all([...t.layouts,t.leaf].map(n=>n?.[1]()))}async function lt(e,t,n){_=e.state;const a=document.querySelector("style[data-sveltekit]");if(a&&a.remove(),Object.assign(k,e.props.page),Pe=new v.root({target:t,props:{...e.props,stores:C,components:ae},hydrate:n,sync:!1}),await Promise.resolve(),ct(x),n){const r={from:null,to:{params:_.params,route:{id:_.route?.id??null},url:new URL(location.href)},willUnload:!1,type:"enter",complete:Promise.resolve()};M.forEach(i=>i(r))}re=!0}function se({url:e,params:t,branch:n,status:a,error:r,route:i,form:o}){let s="never";if(A&&(e.pathname===A||e.pathname===A+"/"))s="always";else for(const u of n)u?.slash!==void 0&&(s=u.slash);e.pathname=_t(e.pathname,s),e.search=e.search;const c={type:"loaded",state:{url:e,params:t,branch:n,error:r,route:i},props:{constructors:Nt(n).map(u=>u.node.component),page:je(k)}};o!==void 0&&(c.props.form=o);let l={},d=!k,h=0;for(let u=0;u(s&&(c.route=!0),f[u])}),params:new Proxy(a,{get:(f,u)=>(s&&c.params.add(u),f[u])}),data:i?.data??null,url:yt(n,()=>{s&&(c.url=!0)},f=>{s&&c.search_params.add(f)},v.hash),async fetch(f,u){f instanceof Request&&(u={body:f.method==="GET"||f.method==="HEAD"?void 0:await f.blob(),cache:f.cache,credentials:f.credentials,headers:[...f.headers].length>0?f?.headers:void 0,integrity:f.integrity,keepalive:f.keepalive,method:f.method,mode:f.mode,redirect:f.redirect,referrer:f.referrer,referrerPolicy:f.referrerPolicy,signal:f.signal,...u});const{resolved:p,promise:w}=ut(f,u,n);return s&&d(p.href),w},setHeaders:()=>{},depends:d,parent(){return s&&(c.parent=!0),t()},untrack(f){s=!1;try{return f()}finally{s=!0}}};o=await l.universal.load.call(null,h)??null}return{node:l,loader:e,server:i,universal:l.universal?.load?{type:"data",data:o,uses:c}:null,data:o??i?.data??null,slash:l.universal?.trailingSlash??i?.slash}}function ut(e,t,n){let a=e instanceof Request?e.url:e;const r=new URL(a,n);r.origin===n.origin&&(a=r.href.slice(n.origin.length));const i=re?Rt(a,r.href,t):St(a,t);return{resolved:r,promise:i}}function Wt(e,t,n,a,r,i){if(Te)return!0;if(!r)return!1;if(r.parent&&e||r.route&&t||r.url&&n)return!0;for(const o of r.search_params)if(a.has(o))return!0;for(const o of r.params)if(i[o]!==_.params[o])return!0;for(const o of r.dependencies)if(ne.some(s=>s(new URL(o))))return!0;return!1}function Oe(e,t){return e?.type==="data"?e:e?.type==="skip"?t??null:null}function Yt(e,t){if(!e)return new Set(t.searchParams.keys());const n=new Set([...e.searchParams.keys(),...t.searchParams.keys()]);for(const a of n){const r=e.searchParams.getAll(a),i=t.searchParams.getAll(a);r.every(o=>i.includes(o))&&i.every(o=>r.includes(o))&&n.delete(a)}return n}function Jt({error:e,url:t,route:n,params:a}){return{type:"loaded",state:{error:e,url:t,route:n,params:a,branch:[]},props:{page:je(k),constructors:[]}}}async function ft({id:e,invalidating:t,url:n,params:a,route:r,preload:i}){if(R?.id===e)return oe.delete(R.token),R.promise;const{errors:o,layouts:s,leaf:c}=r,l=[...s,c];o.forEach(m=>m?.().catch(()=>{})),l.forEach(m=>m?.[1]().catch(()=>{}));const d=_.url?e!==ie(_.url):!1,h=_.route?r.id!==_.route.id:!1,f=Yt(_.url,n);let u=!1;const p=l.map(async(m,g)=>{if(!m)return;const E=_.branch[g];return m[1]===E?.loader&&!Wt(u,h,d,f,E.universal?.uses,a)?E:(u=!0,Ie({loader:m[1],url:n,params:a,route:r,parent:async()=>{const O={};for(let L=0;L{});const w=[];for(let m=0;mPromise.resolve({}),server_data_node:Oe(i)}),s={node:await te(),loader:te,universal:null,server:null,data:null};return se({url:n,params:r,branch:[o,s],status:e,error:t,route:null})}catch(o){if(o instanceof Ee)return Mt(new URL(o.location,location.href),{},0);throw o}}async function Xt(e){const t=e.href;if(Q.has(t))return Q.get(t);let n;try{const a=(async()=>{let r=await v.hooks.reroute({url:new URL(e),fetch:async(i,o)=>ut(i,o,e).promise})??e;if(typeof r=="string"){const i=new URL(e);v.hash?i.hash=r:i.pathname=r,r=i}return r})();Q.set(t,a),n=await a}catch{Q.delete(t);return}return n}async function ue(e,t){if(e&&!le(e,A,v.hash)){const n=await Xt(e);if(!n)return;const a=Qt(n);for(const r of Ue){const i=r.exec(a);if(i)return{id:ie(e),invalidating:t,route:r,params:vt(i),url:e}}}}function Qt(e){return wt(v.hash?e.hash.replace(/^#/,"").replace(/[?#].+/,""):e.pathname.slice(A.length))||"/"}function ie(e){return(v.hash?e.hash.replace(/^#/,""):e.pathname)+e.search}function dt({url:e,type:t,intent:n,delta:a,event:r}){let i=!1;const o=Ce(_,n,e,t);a!==void 0&&(o.navigation.delta=a),r!==void 0&&(o.navigation.event=r);const s={...o.navigation,cancel:()=>{i=!0,o.reject(new Error("navigation cancelled"))}};return z||rt.forEach(c=>c(s)),i?null:o}async function K({type:e,url:t,popped:n,keepfocus:a,noscroll:r,replace_state:i,state:o={},redirect_count:s=0,nav_token:c={},accept:l=Fe,block:d=Fe,event:h}){const f=N;N=c;const u=await ue(t,!1),p=e==="enter"?Ce(_,u,t,e):dt({url:t,type:e,delta:n?.delta,intent:u,event:h});if(!p){d(),N===c&&(N=f);return}const w=y,m=x;l(),z=!0,re&&p.navigation.type!=="enter"&&C.navigating.set(W.current=p.navigation);let g=u&&await ft(u);if(!g){if(le(t,A,v.hash))return await J(t,i);g=await ht(t,{id:null},await X(new Se(404,"Not Found",`Not found: ${t.pathname}`),{url:t,params:{},route:{id:null}}),404,i)}if(t=u?.url||t,N!==c)return p.reject(new Error("navigation aborted")),!1;if(g.type==="redirect"){if(s<20){await K({type:e,url:new URL(g.location,t),popped:n,keepfocus:a,noscroll:r,replace_state:i,state:o,redirect_count:s+1,nav_token:c}),p.fulfil(void 0);return}g=await $e({status:500,error:await X(new Error("Redirect loop"),{url:t,params:{},route:{id:null}}),url:t,route:{id:null}})}else g.props.page.status>=400&&await C.updated.check()&&(await at(),await J(t,i));if(Gt(),Le(w),it(m),g.props.page.url.pathname!==t.pathname&&(t.pathname=g.props.page.url.pathname),o=n?n.state:o,!n){const b=i?0:1,D={[B]:y+=b,[H]:x+=b,[ze]:o};(i?history.replaceState:history.pushState).call(history,D,"",t),i||Kt(y,x)}const E=u&&R?.id===u.id?R.fork:null;R=null,g.props.page.state=o;let S;if(re){const b=(await Promise.all(Array.from(Ft,$=>$(p.navigation)))).filter($=>typeof $=="function");if(b.length>0){let $=function(){b.forEach(fe=>{M.delete(fe)})};b.push($),b.forEach(fe=>{M.add(fe)})}_=g.state,g.props.page&&(g.props.page.url=t);const D=E&&await E;D?S=D.commit():(Pe.$set(g.props),nt(g.props.page),S=mt?.()),st=!0}else await lt(g,we,!1);const{activeElement:O}=document;await S,await Z(),await Z();let L=n?n.scroll:r?ce():null;if(Ge){const b=t.hash&&document.getElementById(pt(t));if(L)scrollTo(L.x,L.y);else if(b){b.scrollIntoView();const{top:D,left:$}=b.getBoundingClientRect();L={x:pageXOffset+$,y:pageYOffset+D}}else scrollTo(0,0)}const gt=document.activeElement!==O&&document.activeElement!==document.body;!a&&!gt&&rn(t,L),Ge=!0,g.props.page&&Object.assign(k,g.props.page),z=!1,e==="popstate"&&ct(x),p.fulfil(void 0),M.forEach(b=>b(p.navigation)),C.navigating.set(W.current=null)}async function ht(e,t,n,a,r){return e.origin===xe&&e.pathname===location.pathname&&!ot?await $e({status:a,error:n,url:e,route:t}):await J(e,r)}function Zt(){let e,t,n;I.addEventListener("mousemove",s=>{const c=s.target;clearTimeout(e),e=setTimeout(()=>{i(c,j.hover)},20)});function a(s){s.defaultPrevented||i(s.composedPath()[0],j.tap)}I.addEventListener("mousedown",a),I.addEventListener("touchstart",a,{passive:!0});const r=new IntersectionObserver(s=>{for(const c of s)c.isIntersecting&&(ge(new URL(c.target.href)),r.unobserve(c.target))},{threshold:0});async function i(s,c){const l=Ze(s,I),d=l===t&&c>=n;if(!l||d)return;const{url:h,external:f,download:u}=me(l,A,v.hash);if(f||u)return;const p=ee(l),w=h&&ie(_.url)===ie(h);if(!(p.reload||w))if(c<=p.preload_data){t=l,n=j.tap;const m=await ue(h,!1);if(!m)return;Ht(m)}else c<=p.preload_code&&(t=l,n=c,ge(h))}function o(){r.disconnect();for(const s of I.querySelectorAll("a")){const{url:c,external:l,download:d}=me(s,A,v.hash);if(l||d)continue;const h=ee(s);h.reload||(h.preload_code===j.viewport&&r.observe(s),h.preload_code===j.eager&&ge(c))}}M.add(o),o()}function X(e,t){if(e instanceof ke)return e.body;const n=Ae(e),a=qt(e);return v.hooks.handleError({error:e,event:t,status:n,message:a})??{message:a}}function en(e){if(typeof e=="function")ne.push(e);else{const{href:t}=new URL(e,location.href);ne.push(n=>n.href===t)}}function tn(){history.scrollRestoration="manual",addEventListener("beforeunload",t=>{let n=!1;if(He(),!z){const a=Ce(_,void 0,null,"leave"),r={...a.navigation,cancel:()=>{n=!0,a.reject(new Error("navigation cancelled"))}};rt.forEach(i=>i(r))}n?(t.preventDefault(),t.returnValue=""):history.scrollRestoration="auto"}),addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&He()}),navigator.connection?.saveData||Zt(),I.addEventListener("click",async t=>{if(t.button||t.which!==1||t.metaKey||t.ctrlKey||t.shiftKey||t.altKey||t.defaultPrevented)return;const n=Ze(t.composedPath()[0],I);if(!n)return;const{url:a,external:r,target:i,download:o}=me(n,A,v.hash);if(!a)return;if(i==="_parent"||i==="_top"){if(window.parent!==window)return}else if(i&&i!=="_self")return;const s=ee(n);if(!(n instanceof SVGAElement)&&a.protocol!==location.protocol&&!(a.protocol==="https:"||a.protocol==="http:")||o)return;const[l,d]=(v.hash?a.hash.replace(/^#/,""):a.href).split("#"),h=l===de(location);if(r||s.reload&&(!h||!d)){dt({url:a,type:"link",event:t})?z=!0:t.preventDefault();return}if(d!==void 0&&h){const[,f]=_.url.href.split("#");if(f===d){if(t.preventDefault(),d===""||d==="top"&&n.ownerDocument.getElementById("top")===null)scrollTo({top:0});else{const u=n.ownerDocument.getElementById(decodeURIComponent(d));u&&(u.scrollIntoView(),u.focus())}return}if(F=!0,Le(y),e(a),!s.replace_state)return;F=!1}t.preventDefault(),await new Promise(f=>{requestAnimationFrame(()=>{setTimeout(f,0)}),setTimeout(f,100)}),await K({type:"link",url:a,keepfocus:s.keepfocus,noscroll:s.noscroll,replace_state:s.replace_state??a.href===location.href,event:t})}),I.addEventListener("submit",t=>{if(t.defaultPrevented)return;const n=HTMLFormElement.prototype.cloneNode.call(t.target),a=t.submitter;if((a?.formTarget||n.target)==="_blank"||(a?.formMethod||n.method)!=="get")return;const o=new URL(a?.hasAttribute("formaction")&&a?.formAction||n.action);if(le(o,A,!1))return;const s=t.target,c=ee(s);if(c.reload)return;t.preventDefault(),t.stopPropagation();const l=new FormData(s,a);o.search=new URLSearchParams(l).toString(),K({type:"form",url:o,keepfocus:c.keepfocus,noscroll:c.noscroll,replace_state:c.replace_state??o.href===location.href,event:t})}),addEventListener("popstate",async t=>{if(!ye){if(t.state?.[B]){const n=t.state[B];if(N={},n===y)return;const a=q[n],r=t.state[ze]??{},i=new URL(t.state[$t]??location.href),o=t.state[H],s=_.url?de(location)===de(_.url):!1;if(o===x&&(st||s)){r!==k.state&&(k.state=r),e(i),q[y]=ce(),a&&scrollTo(a.x,a.y),y=n;return}const l=n-y;await K({type:"popstate",url:i,popped:{state:r,scroll:a,delta:l},accept:()=>{y=n,x=o},block:()=>{history.go(-l)},nav_token:N,event:t})}else if(!F){const n=new URL(location.href);e(n),v.hash&&location.reload()}}}),addEventListener("hashchange",()=>{F&&(F=!1,history.replaceState({...history.state,[B]:++y,[H]:x},"",location.href))});for(const t of document.querySelectorAll("link"))Bt.has(t.rel)&&(t.href=t.href);addEventListener("pageshow",t=>{t.persisted&&C.navigating.set(W.current=null)});function e(t){_.url=k.url=t,C.page.set(je(k)),C.page.notify()}}async function nn(e,{status:t=200,error:n,node_ids:a,params:r,route:i,server_route:o,data:s,form:c}){ot=!0;const l=new URL(location.href);let d;({params:r={},route:i={id:null}}=await ue(l,!1)||{}),d=Ue.find(({id:u})=>u===i.id);let h,f=!0;try{const u=a.map(async(w,m)=>{const g=s[m];return g?.uses&&(g.uses=an(g.uses)),Ie({loader:v.nodes[w],url:l,params:r,route:i,parent:async()=>{const E={};for(let S=0;S{const s=history.state;ye=!0,location.replace(`#${a}`),v.hash&&location.replace(e.hash),history.replaceState(s,"",e.hash),scrollTo(i,o),ye=!1})}else{const i=document.body,o=i.getAttribute("tabindex");i.tabIndex=-1,i.focus({preventScroll:!0,focusVisible:!1}),o!==null?i.setAttribute("tabindex",o):i.removeAttribute("tabindex")}const r=getSelection();if(r&&r.type!=="None"){const i=[];for(let o=0;o{if(r.rangeCount===i.length){for(let o=0;o{r=c,i=l});return o.catch(()=>{}),{navigation:{from:{params:e.params,route:{id:e.route?.id??null},url:e.url},to:n&&{params:t?.params??null,route:{id:t?.route?.id??null},url:n},willUnload:!t,type:a,complete:o},fulfil:r,reject:i}}function je(e){return{data:e.data,error:e.error,form:e.form,params:e.params,route:e.route,state:e.state,status:e.status,url:e.url}}function on(e){const t=new URL(e);return t.hash=decodeURIComponent(e.hash),t}function pt(e){let t;if(v.hash){const[,,n]=e.hash.split("#",3);t=n??""}else t=e.hash.slice(1);return decodeURIComponent(t)}export{hn as a,ln as l,C as s}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CQO205-B.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/CQO205-B.js deleted file mode 100644 index dd5ca2f..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CQO205-B.js +++ /dev/null @@ -1 +0,0 @@ -var Ut=Array.isArray,Bt=Array.prototype.indexOf,Pn=Array.from,In=Object.defineProperty,ce=Object.getOwnPropertyDescriptor,Vt=Object.getOwnPropertyDescriptors,Gt=Object.prototype,$t=Array.prototype,lt=Object.getPrototypeOf,nt=Object.isExtensible;const we=()=>{};function Cn(e){return e()}function zt(e){for(var t=0;t{e=r,t=s});return{promise:n,resolve:e,reject:t}}function Fn(e,t){if(Array.isArray(e))return e;if(!(Symbol.iterator in e))return Array.from(e);const n=[];for(const r of e)if(n.push(r),n.length===t)break;return n}const y=2,Ue=4,Re=8,Kt=1<<24,L=16,j=32,te=64,Be=128,D=512,E=1024,A=2048,N=4096,I=8192,H=16384,Ve=32768,ye=65536,Ce=1<<17,ot=1<<18,he=1<<19,ct=1<<20,Mn=1<<25,W=32768,Fe=1<<21,Ge=1<<22,U=1<<23,_e=Symbol("$state"),Ln=Symbol("legacy props"),jn=Symbol(""),re=new class extends Error{name="StaleReactionError";message="The reaction that called `getAbortSignal()` was re-run or destroyed"},$e=3,_t=8;function Xt(e){throw new Error("https://svelte.dev/e/experimental_async_required")}function Yn(e){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function Zt(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function Wt(e){throw new Error("https://svelte.dev/e/effect_in_teardown")}function Jt(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function Qt(e){throw new Error("https://svelte.dev/e/effect_orphan")}function en(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function tn(){throw new Error("https://svelte.dev/e/fork_discarded")}function nn(){throw new Error("https://svelte.dev/e/fork_timing")}function Hn(){throw new Error("https://svelte.dev/e/hydration_failed")}function Un(e){throw new Error("https://svelte.dev/e/props_invalid_value")}function rn(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function sn(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function fn(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function Bn(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}const Vn=1,Gn=2,$n=4,zn=8,Kn=16,Xn=1,Zn=2,Wn=4,Jn=8,Qn=16,er=1,tr=2,an="[",ln="[!",un="]",ze={},m=Symbol(),nr="http://www.w3.org/1999/xhtml";function Ke(e){console.warn("https://svelte.dev/e/hydration_mismatch")}function rr(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}let J=!1;function sr(e){J=e}let x;function fe(e){if(e===null)throw Ke(),ze;return x=e}function fr(){return fe($(x))}function ir(e){if(J){if($(x)!==null)throw Ke(),ze;x=e}}function ar(e=1){if(J){for(var t=e,n=x;t--;)n=$(n);x=n}}function lr(e=!0){for(var t=0,n=x;;){if(n.nodeType===_t){var r=n.data;if(r===un){if(t===0)return n;t-=1}else(r===an||r===ln)&&(t+=1)}var s=$(n);e&&n.remove(),n=s}}function ur(e){if(!e||e.nodeType!==_t)throw Ke(),ze;return e.data}function vt(e){return e===this.v}function dt(e,t){return e!=e?t==t:e!==t||e!==null&&typeof e=="object"||typeof e=="function"}function ht(e){return!dt(e,this.v)}let ke=!1;function or(){ke=!0}let g=null;function Ee(e){g=e}function cr(e,t=!1,n){g={p:g,i:!1,c:null,e:null,s:e,x:null,l:ke&&!t?{s:null,u:null,$:[]}:null}}function _r(e){var t=g,n=t.e;if(n!==null){t.e=null;for(var r of n)kt(r)}return t.i=!0,g=t.p,{}}function pe(){return!ke||g!==null&&g.l===null}let z=[];function pt(){var e=z;z=[],zt(e)}function on(e){if(z.length===0&&!ve){var t=z;queueMicrotask(()=>{t===z&&pt()})}z.push(e)}function cn(){for(;z.length>0;)pt()}function _n(e){var t=h;if(t===null)return _.f|=U,e;if((t.f&Ve)===0){if((t.f&Be)===0)throw e;t.b.error(e)}else ge(e,t)}function ge(e,t){for(;t!==null;){if((t.f&Be)!==0)try{t.b.error(e);return}catch(n){e=n}t=t.parent}throw e}const K=new Set;let p=null,Pe=null,T=null,k=[],Oe=null,Me=!1,ve=!1;class V{committed=!1;current=new Map;previous=new Map;#r=new Set;#s=new Set;#e=0;#t=0;#a=null;#f=new Set;#i=new Set;skipped_effects=new Set;is_fork=!1;is_deferred(){return this.is_fork||this.#t>0}process(t){k=[],Pe=null,this.apply();var n={parent:null,effect:null,effects:[],render_effects:[]};for(const r of t)this.#l(r,n);this.is_fork||this.#o(),this.is_deferred()?(this.#n(n.effects),this.#n(n.render_effects)):(Pe=this,p=null,rt(n.render_effects),rt(n.effects),Pe=null,this.#a?.resolve()),T=null}#l(t,n){t.f^=E;for(var r=t.first;r!==null;){var s=r.f,f=(s&(j|te))!==0,u=f&&(s&E)!==0,l=u||(s&I)!==0||this.skipped_effects.has(r);if((r.f&Be)!==0&&r.b?.is_pending()&&(n={parent:n,effect:r,effects:[],render_effects:[]}),!l&&r.fn!==null){f?r.f^=E:(s&Ue)!==0?n.effects.push(r):ue(r)&&((r.f&L)!==0&&this.#f.add(r),ae(r));var a=r.first;if(a!==null){r=a;continue}}var i=r.parent;for(r=r.next;r===null&&i!==null;)i===n.effect&&(this.#n(n.effects),this.#n(n.render_effects),n=n.parent),r=i.next,i=i.parent}}#n(t){for(const n of t)(n.f&A)!==0?this.#f.add(n):(n.f&N)!==0&&this.#i.add(n),this.#u(n.deps),w(n,E)}#u(t){if(t!==null)for(const n of t)(n.f&y)===0||(n.f&W)===0||(n.f^=W,this.#u(n.deps))}capture(t,n){this.previous.has(t)||this.previous.set(t,n),(t.f&U)===0&&(this.current.set(t,t.v),T?.set(t,t.v))}activate(){p=this,this.apply()}deactivate(){p===this&&(p=null,T=null)}flush(){if(this.activate(),k.length>0){if(je(),p!==null&&p!==this)return}else this.#e===0&&this.process([]);this.deactivate()}discard(){for(const t of this.#s)t(this);this.#s.clear()}#o(){if(this.#t===0){for(const t of this.#r)t();this.#r.clear()}this.#e===0&&this.#c()}#c(){if(K.size>1){this.previous.clear();var t=T,n=!0,r={parent:null,effect:null,effects:[],render_effects:[]};for(const f of K){if(f===this){n=!1;continue}const u=[];for(const[a,i]of this.current){if(f.current.has(a))if(n&&i!==f.current.get(a))f.current.set(a,i);else continue;u.push(a)}if(u.length===0)continue;const l=[...f.current.keys()].filter(a=>!this.current.has(a));if(l.length>0){var s=k;k=[];const a=new Set,i=new Map;for(const o of u)wt(o,l,a,i);if(k.length>0){p=f,f.apply();for(const o of k)f.#l(o,r);f.deactivate()}k=s}}p=null,T=t}this.committed=!0,K.delete(this)}increment(t){this.#e+=1,t&&(this.#t+=1)}decrement(t){this.#e-=1,t&&(this.#t-=1),this.revive()}revive(){for(const t of this.#f)this.#i.delete(t),w(t,A),Q(t);for(const t of this.#i)w(t,N),Q(t);this.flush()}oncommit(t){this.#r.add(t)}ondiscard(t){this.#s.add(t)}settled(){return(this.#a??=ut()).promise}static ensure(){if(p===null){const t=p=new V;K.add(p),ve||V.enqueue(()=>{p===t&&t.flush()})}return p}static enqueue(t){on(t)}apply(){}}function Le(e){var t=ve;ve=!0;try{var n;for(e&&(p!==null&&je(),n=e());;){if(cn(),k.length===0&&(p?.flush(),k.length===0))return Oe=null,n;je()}}finally{ve=t}}function je(){var e=X;Me=!0;var t=null;try{var n=0;for(Se(!0);k.length>0;){var r=V.ensure();if(n++>1e3){var s,f;vn()}r.process(k),B.clear()}}finally{Me=!1,Se(e),Oe=null}}function vn(){try{en()}catch(e){ge(e,Oe)}}let F=null;function rt(e){var t=e.length;if(t!==0){for(var n=0;n0)){B.clear();for(const s of F){if((s.f&(H|I))!==0)continue;const f=[s];let u=s.parent;for(;u!==null;)F.has(u)&&(F.delete(u),f.push(u)),u=u.parent;for(let l=f.length-1;l>=0;l--){const a=f[l];(a.f&(H|I))===0&&ae(a)}}F.clear()}}F=null}}function wt(e,t,n,r){if(!n.has(e)&&(n.add(e),e.reactions!==null))for(const s of e.reactions){const f=s.f;(f&y)!==0?wt(s,t,n,r):(f&(Ge|L))!==0&&(f&A)===0&&Et(s,t,r)&&(w(s,A),Q(s))}}function yt(e,t){if(e.reactions!==null)for(const n of e.reactions){const r=n.f;(r&y)!==0?yt(n,t):(r&Ce)!==0&&(w(n,A),t.add(n))}}function Et(e,t,n){const r=n.get(e);if(r!==void 0)return r;if(e.deps!==null)for(const s of e.deps){if(t.includes(s))return!0;if((s.f&y)!==0&&Et(s,t,n))return n.set(s,!0),!0}return n.set(e,!1),!1}function Q(e){for(var t=Oe=e;t.parent!==null;){t=t.parent;var n=t.f;if(Me&&t===h&&(n&L)!==0&&(n&ot)===0)return;if((n&(te|j))!==0){if((n&E)===0)return;t.f^=E}}k.push(t)}function vr(e){Xt(),p!==null&&nn();var t=V.ensure();t.is_fork=!0,T=new Map;var n=!1,r=t.settled();Le(e),T=null;for(var[s,f]of t.previous)s.v=f;return{commit:async()=>{if(n){await r;return}K.has(t)||tn(),n=!0,t.is_fork=!1;for(var[u,l]of t.current)u.v=l;Le(()=>{var a=new Set;for(var i of t.current.keys())yt(i,a);En(a),Tt()}),t.revive(),await r},discard:()=>{!n&&K.has(t)&&(K.delete(t),t.discard())}}}function dn(e,t,n,r){const s=pe()?Xe:wn;if(n.length===0&&e.length===0){r(t.map(s));return}var f=p,u=h,l=hn();function a(){Promise.all(n.map(i=>pn(i))).then(i=>{l();try{r([...t.map(s),...i])}catch(o){(u.f&H)===0&&ge(o,u)}f?.deactivate(),me()}).catch(i=>{ge(i,u)})}e.length>0?Promise.all(e).then(()=>{l();try{return a()}finally{f?.deactivate(),me()}}):a()}function hn(){var e=h,t=_,n=g,r=p;return function(f=!0){ie(e),G(t),Ee(n),f&&r?.activate()}}function me(){ie(null),G(null),Ee(null)}function Xe(e){var t=y|A,n=_!==null&&(_.f&y)!==0?_:null;return h!==null&&(h.f|=he),{ctx:g,deps:null,effects:null,equals:vt,f:t,fn:e,reactions:null,rv:0,v:m,wv:0,parent:n??h,ac:null}}function pn(e,t){let n=h;n===null&&Zt();var r=n.b,s=void 0,f=We(m),u=!_,l=new Map;return An(()=>{var a=ut();s=a.promise;try{Promise.resolve(e()).then(a.resolve,a.reject).then(()=>{i===p&&i.committed&&i.deactivate(),me()})}catch(c){a.reject(c),me()}var i=p;if(u){var o=!r.is_pending();r.update_pending_count(1),i.increment(o),l.get(i)?.reject(re),l.delete(i),l.set(i,a)}const v=(c,d=void 0)=>{if(i.activate(),d)d!==re&&(f.f|=U,qe(f,d));else{(f.f&U)!==0&&(f.f^=U),qe(f,c);for(const[O,De]of l){if(l.delete(O),O===i)break;De.reject(re)}}u&&(r.update_pending_count(-1),i.decrement(o))};a.promise.then(v,c=>v(null,c||"unknown"))}),Tn(()=>{for(const a of l.values())a.reject(re)}),new Promise(a=>{function i(o){function v(){o===s?a(f):i(s)}o.then(v,v)}i(s)})}function dr(e){const t=Xe(e);return Ft(t),t}function wn(e){const t=Xe(e);return t.equals=ht,t}function gt(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;nse(e))),t}function Y(e,t,n=!1){_!==null&&(!P||(_.f&Ce)!==0)&&pe()&&(_.f&(y|L|Ge|Ce))!==0&&!M?.includes(e)&&fn();let r=n?oe(t):t;return qe(e,r)}function qe(e,t){if(!e.equals(t)){var n=e.v;le?B.set(e,t):B.set(e,n),e.v=t;var r=V.ensure();r.capture(e,n),(e.f&y)!==0&&((e.f&A)!==0&&Ze(e),w(e,(e.f&D)!==0?E:N)),e.wv=Lt(),At(e,A),pe()&&h!==null&&(h.f&E)!==0&&(h.f&(j|te))===0&&(R===null?kn([e]):R.push(e)),!r.is_fork&&be.size>0&&!bt&&Tt()}return t}function Tt(){bt=!1;var e=X;Se(!0);const t=Array.from(be);try{for(const n of t)(n.f&E)!==0&&w(n,N),ue(n)&&ae(n)}finally{Se(e)}be.clear()}function Ie(e){Y(e,e.v+1)}function At(e,t){var n=e.reactions;if(n!==null)for(var r=pe(),s=n.length,f=0;f{if(Z===f)return l();var a=_,i=Z;G(null),at(f);var o=l();return G(a),at(i),o};return r&&n.set("length",q(e.length)),new Proxy(e,{defineProperty(l,a,i){(!("value"in i)||i.configurable===!1||i.enumerable===!1||i.writable===!1)&&rn();var o=n.get(a);return o===void 0?o=u(()=>{var v=q(i.value);return n.set(a,v),v}):Y(o,i.value,!0),!0},deleteProperty(l,a){var i=n.get(a);if(i===void 0){if(a in l){const o=u(()=>q(m));n.set(a,o),Ie(s)}}else Y(i,m),Ie(s);return!0},get(l,a,i){if(a===_e)return e;var o=n.get(a),v=a in l;if(o===void 0&&(!v||ce(l,a)?.writable)&&(o=u(()=>{var d=oe(v?l[a]:m),O=q(d);return O}),n.set(a,o)),o!==void 0){var c=se(o);return c===m?void 0:c}return Reflect.get(l,a,i)},getOwnPropertyDescriptor(l,a){var i=Reflect.getOwnPropertyDescriptor(l,a);if(i&&"value"in i){var o=n.get(a);o&&(i.value=se(o))}else if(i===void 0){var v=n.get(a),c=v?.v;if(v!==void 0&&c!==m)return{enumerable:!0,configurable:!0,value:c,writable:!0}}return i},has(l,a){if(a===_e)return!0;var i=n.get(a),o=i!==void 0&&i.v!==m||Reflect.has(l,a);if(i!==void 0||h!==null&&(!o||ce(l,a)?.writable)){i===void 0&&(i=u(()=>{var c=o?oe(l[a]):m,d=q(c);return d}),n.set(a,i));var v=se(i);if(v===m)return!1}return o},set(l,a,i,o){var v=n.get(a),c=a in l;if(r&&a==="length")for(var d=i;dq(m)),n.set(d+"",O))}if(v===void 0)(!c||ce(l,a)?.writable)&&(v=u(()=>q(void 0)),Y(v,oe(i)),n.set(a,v));else{c=v.v!==m;var De=u(()=>oe(i));Y(v,De)}var et=Reflect.getOwnPropertyDescriptor(l,a);if(et?.set&&et.set.call(o,i),!c){if(r&&typeof a=="string"){var tt=n.get("length"),Ne=Number(a);Number.isInteger(Ne)&&Ne>=tt.v&&Y(tt,Ne+1)}Ie(s)}return!0},ownKeys(l){se(s);var a=Reflect.ownKeys(l).filter(v=>{var c=n.get(v);return c===void 0||c.v!==m});for(var[i,o]of n)o.v!==m&&!(i in l)&&a.push(i);return a},setPrototypeOf(){sn()}})}var st,gn,St,xt;function wr(){if(st===void 0){st=window,gn=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;St=ce(t,"firstChild").get,xt=ce(t,"nextSibling").get,nt(e)&&(e.__click=void 0,e.__className=void 0,e.__attributes=null,e.__style=void 0,e.__e=void 0),nt(n)&&(n.__t=void 0)}}function Te(e=""){return document.createTextNode(e)}function Ye(e){return St.call(e)}function $(e){return xt.call(e)}function yr(e,t){if(!J)return Ye(e);var n=Ye(x);if(n===null)n=x.appendChild(Te());else if(t&&n.nodeType!==$e){var r=Te();return n?.before(r),fe(r),r}return fe(n),n}function Er(e,t=!1){if(!J){var n=Ye(e);return n instanceof Comment&&n.data===""?$(n):n}if(t&&x?.nodeType!==$e){var r=Te();return x?.before(r),fe(r),r}return x}function gr(e,t=1,n=!1){let r=J?x:e;for(var s;t--;)s=r,r=$(r);if(!J)return r;if(n&&r?.nodeType!==$e){var f=Te();return r===null?s?.after(f):r.before(f),fe(f),f}return fe(r),r}function mr(e){e.textContent=""}function br(){return!1}let ft=!1;function mn(){ft||(ft=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(const t of e.target.elements)t.__on_r?.()})},{capture:!0}))}function Je(e){var t=_,n=h;G(null),ie(null);try{return e()}finally{G(t),ie(n)}}function Tr(e,t,n,r=n){e.addEventListener(t,()=>Je(n));const s=e.__on_r;s?e.__on_r=()=>{s(),r(!0)}:e.__on_r=()=>r(!0),mn()}function Rt(e){h===null&&(_===null&&Qt(),Jt()),le&&Wt()}function bn(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function C(e,t,n){var r=h;r!==null&&(r.f&I)!==0&&(e|=I);var s={ctx:g,deps:null,nodes:null,f:e|A|D,first:null,fn:t,last:null,next:null,parent:r,b:r&&r.b,prev:null,teardown:null,wv:0,ac:null};if(n)try{ae(s),s.f|=Ve}catch(l){throw ee(s),l}else t!==null&&Q(s);var f=s;if(n&&f.deps===null&&f.teardown===null&&f.nodes===null&&f.first===f.last&&(f.f&he)===0&&(f=f.first,(e&L)!==0&&(e&ye)!==0&&f!==null&&(f.f|=ye)),f!==null&&(f.parent=r,r!==null&&bn(f,r),_!==null&&(_.f&y)!==0&&(e&te)===0)){var u=_;(u.effects??=[]).push(f)}return s}function Ae(){return _!==null&&!P}function Tn(e){const t=C(Re,null,!1);return w(t,E),t.teardown=e,t}function Ar(e){Rt();var t=h.f,n=!_&&(t&j)!==0&&(t&Ve)===0;if(n){var r=g;(r.e??=[]).push(e)}else return kt(e)}function kt(e){return C(Ue|ct,e,!1)}function Sr(e){return Rt(),C(Re|ct,e,!0)}function xr(e){V.ensure();const t=C(te|he,e,!0);return(n={})=>new Promise(r=>{n.outro?Rn(t,()=>{ee(t),r(void 0)}):(ee(t),r(void 0))})}function Rr(e){return C(Ue,e,!1)}function kr(e,t){var n=g,r={effect:null,ran:!1,deps:e};n.l.$.push(r),r.effect=Ot(()=>{e(),!r.ran&&(r.ran=!0,Qe(t))})}function Or(){var e=g;Ot(()=>{for(var t of e.l.$){t.deps();var n=t.effect;(n.f&E)!==0&&w(n,N),ue(n)&&ae(n),t.ran=!1}})}function An(e){return C(Ge|he,e,!0)}function Ot(e,t=0){return C(Re|t,e,!0)}function Dr(e,t=[],n=[],r=[]){dn(r,t,n,s=>{C(Re,()=>e(...s.map(se)),!0)})}function Nr(e,t=0){var n=C(L|t,e,!0);return n}function Pr(e){return C(j|he,e,!0)}function Dt(e){var t=e.teardown;if(t!==null){const n=le,r=_;it(!0),G(null);try{t.call(null)}finally{it(n),G(r)}}}function Nt(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){const s=n.ac;s!==null&&Je(()=>{s.abort(re)});var r=n.next;(n.f&te)!==0?n.parent=null:ee(n,t),n=r}}function Sn(e){for(var t=e.first;t!==null;){var n=t.next;(t.f&j)===0&&ee(t),t=n}}function ee(e,t=!0){var n=!1;(t||(e.f&ot)!==0)&&e.nodes!==null&&e.nodes.end!==null&&(xn(e.nodes.start,e.nodes.end),n=!0),Nt(e,t&&!n),xe(e,0),w(e,H);var r=e.nodes&&e.nodes.t;if(r!==null)for(const f of r)f.stop();Dt(e);var s=e.parent;s!==null&&s.first!==null&&Pt(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=null}function xn(e,t){for(;e!==null;){var n=e===t?null:$(e);e.remove(),e=n}}function Pt(e){var t=e.parent,n=e.prev,r=e.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),t!==null&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function Rn(e,t,n=!0){var r=[];It(e,r,!0);var s=()=>{n&&ee(e),t&&t()},f=r.length;if(f>0){var u=()=>--f||s();for(var l of r)l.out(u)}else s()}function It(e,t,n){if((e.f&I)===0){e.f^=I;var r=e.nodes&&e.nodes.t;if(r!==null)for(const l of r)(l.is_global||n)&&t.push(l);for(var s=e.first;s!==null;){var f=s.next,u=(s.f&ye)!==0||(s.f&j)!==0&&(e.f&L)!==0;It(s,t,u?n:!1),s=f}}}function Ir(e){Ct(e,!0)}function Ct(e,t){if((e.f&I)!==0){e.f^=I,(e.f&E)===0&&(w(e,A),Q(e));for(var n=e.first;n!==null;){var r=n.next,s=(n.f&ye)!==0||(n.f&j)!==0;Ct(n,s?t:!1),n=r}var f=e.nodes&&e.nodes.t;if(f!==null)for(const u of f)(u.is_global||t)&&u.in()}}function Cr(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var s=n===r?null:$(n);t.append(n),n=s}}let X=!1;function Se(e){X=e}let le=!1;function it(e){le=e}let _=null,P=!1;function G(e){_=e}let h=null;function ie(e){h=e}let M=null;function Ft(e){_!==null&&(M===null?M=[e]:M.push(e))}let b=null,S=0,R=null;function kn(e){R=e}let Mt=1,de=0,Z=de;function at(e){Z=e}function Lt(){return++Mt}function ue(e){var t=e.f;if((t&A)!==0)return!0;if(t&y&&(e.f&=~W),(t&N)!==0){var n=e.deps;if(n!==null)for(var r=n.length,s=0;se.wv)return!0}(t&D)!==0&&T===null&&w(e,E)}return!1}function jt(e,t,n=!0){var r=e.reactions;if(r!==null&&!M?.includes(e))for(var s=0;s{e.ac.abort(re)}),e.ac=null);try{e.f|=Fe;var o=e.fn,v=o(),c=e.deps;if(b!==null){var d;if(xe(e,S),c!==null&&S>0)for(c.length=S+b.length,d=0;de.subscribe(t,n));return r.unsubscribe?()=>r.unsubscribe():r}const ne=[];function jr(e,t=we){let n=null;const r=new Set;function s(l){if(dt(e,l)&&(e=l,n)){const a=!ne.length;for(const i of r)i[1](),ne.push(i,e);if(a){for(let i=0;i{r.delete(i),r.size===0&&n&&(n(),n=null)}}return{set:s,update:f,subscribe:u}}function qr(e){let t;return Nn(e,n=>t=n)(),t}export{jr as $,wn as A,ur as B,lr as C,sr as D,x as E,_t as F,un as G,ln as H,qe as I,p as J,Mn as K,Pr as L,br as M,We as N,Pn as O,Vn as P,Kn as Q,Gn as R,Ir as S,Rn as T,I as U,$ as V,mr as W,ee as X,$n as Y,on as Z,zn as _,_r as a,we as a$,Sr as a0,zt as a1,Cn as a2,Xe as a3,or as a4,mn as a5,jn as a6,nr as a7,lt as a8,Vt as a9,q as aA,Ae as aB,Ie as aC,V as aD,ie as aE,G as aF,Ee as aG,_n as aH,_ as aI,ge as aJ,Bn as aK,he as aL,Be as aM,rr as aN,Tn as aO,Je as aP,gn as aQ,er as aR,tr as aS,Ve as aT,$e as aU,wr as aV,an as aW,ze as aX,Hn as aY,xr as aZ,Ke as a_,Tr as aa,Fr as ab,Ot as ac,Pe as ad,Cr as ae,ye as af,ce as ag,Wn as ah,oe as ai,h as aj,H as ak,Zn as al,Jn as am,le as an,_e as ao,Ln as ap,Un as aq,Xn as ar,Qn as as,Er as at,qr as au,dr as av,Fn as aw,Rr as ax,Le as ay,In as az,g as b,Nn as b0,vr as b1,Mr as b2,yr as c,ke as d,Qe as e,kr as f,Or as g,J as h,Ut as i,se as j,Lr as k,Yn as l,hr as m,ar as n,Y as o,cr as p,pr as q,ir as r,gr as s,Dr as t,Ar as u,Te as v,Nr as w,fe as x,Ye as y,fr as z}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CWb4Vnhz.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/CWb4Vnhz.js deleted file mode 100644 index debe96c..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CWb4Vnhz.js +++ /dev/null @@ -1,2 +0,0 @@ -import{aB as ee,j as V,N as X,ac as te,e as re,aC as U,Z as B,E as f,h as c,aj as v,w as ne,z,F as W,H as se,L as p,aD as S,T as F,v as w,aE as A,aF as m,aG as Y,aH as ie,aI as C,b as Z,ae,I as ue,X as M,x as N,n as oe,C as le,aJ as $,aK as fe,af as he,aL as ce,aM as de,aN as _e,aO as J,aP as pe,az as K,y as I,aQ as ve,aR as ge,aS as be,aT as ye,aU as me,aV as x,aW as Ee,V as Te,aX as P,D as O,aY as we,W as Ne,O as Re,aZ as Se,p as Oe,G as De,a_ as Ae,a as Le,a$ as j,m as Fe,b0 as Me,au as Ce,o as Ie}from"./CQO205-B.js";function xe(t){let e=0,r=X(0),s;return()=>{ee()&&(V(r),te(()=>(e===0&&(s=re(()=>t(()=>U(r)))),e+=1,()=>{B(()=>{e-=1,e===0&&(s?.(),s=void 0,U(r))})})))}}var Pe=he|ce|de;function ke(t,e,r){new He(t,e,r)}class He{parent;#r=!1;#t;#v=c?f:null;#s;#h;#i;#n=null;#e=null;#a=null;#u=null;#o=null;#c=0;#l=0;#d=!1;#f=null;#y=xe(()=>(this.#f=X(this.#c),()=>{this.#f=null}));constructor(e,r,s){this.#t=e,this.#s=r,this.#h=s,this.parent=v.b,this.#r=!!this.#s.pending,this.#i=ne(()=>{if(v.b=this,c){const n=this.#v;z(),n.nodeType===W&&n.data===se?this.#E():this.#m()}else{var i=this.#g();try{this.#n=p(()=>s(i))}catch(n){this.error(n)}this.#l>0?this.#p():this.#r=!1}return()=>{this.#o?.remove()}},Pe),c&&(this.#t=f)}#m(){try{this.#n=p(()=>this.#h(this.#t))}catch(e){this.error(e)}this.#r=!1}#E(){const e=this.#s.pending;e&&(this.#e=p(()=>e(this.#t)),S.enqueue(()=>{var r=this.#g();this.#n=this.#_(()=>(S.ensure(),p(()=>this.#h(r)))),this.#l>0?this.#p():(F(this.#e,()=>{this.#e=null}),this.#r=!1)}))}#g(){var e=this.#t;return this.#r&&(this.#o=w(),this.#t.before(this.#o),e=this.#o),e}is_pending(){return this.#r||!!this.parent&&this.parent.is_pending()}has_pending_snippet(){return!!this.#s.pending}#_(e){var r=v,s=C,i=Z;A(this.#i),m(this.#i),Y(this.#i.ctx);try{return e()}catch(n){return ie(n),null}finally{A(r),m(s),Y(i)}}#p(){const e=this.#s.pending;this.#n!==null&&(this.#u=document.createDocumentFragment(),this.#u.append(this.#o),ae(this.#n,this.#u)),this.#e===null&&(this.#e=p(()=>e(this.#t)))}#b(e){if(!this.has_pending_snippet()){this.parent&&this.parent.#b(e);return}this.#l+=e,this.#l===0&&(this.#r=!1,this.#e&&F(this.#e,()=>{this.#e=null}),this.#u&&(this.#t.before(this.#u),this.#u=null))}update_pending_count(e){this.#b(e),this.#c+=e,this.#f&&ue(this.#f,this.#c)}get_effect_pending(){return this.#y(),V(this.#f)}error(e){var r=this.#s.onerror;let s=this.#s.failed;if(this.#d||!r&&!s)throw e;this.#n&&(M(this.#n),this.#n=null),this.#e&&(M(this.#e),this.#e=null),this.#a&&(M(this.#a),this.#a=null),c&&(N(this.#v),oe(),N(le()));var i=!1,n=!1;const a=()=>{if(i){_e();return}i=!0,n&&fe(),S.ensure(),this.#c=0,this.#a!==null&&F(this.#a,()=>{this.#a=null}),this.#r=this.has_pending_snippet(),this.#n=this.#_(()=>(this.#d=!1,p(()=>this.#h(this.#t)))),this.#l>0?this.#p():this.#r=!1};var h=C;try{m(null),n=!0,r?.(e,a),n=!1}catch(l){$(l,this.#i&&this.#i.parent)}finally{m(h)}s&&B(()=>{this.#a=this.#_(()=>{S.ensure(),this.#d=!0;try{return p(()=>{s(this.#t,()=>e,()=>a)})}catch(l){return $(l,this.#i.parent),null}finally{this.#d=!1}})})}}const Ve=["touchstart","touchmove"];function Be(t){return Ve.includes(t)}const We=new Set,q=new Set;function Ue(t,e,r,s={}){function i(n){if(s.capture||T.call(e,n),!n.cancelBubble)return pe(()=>r?.call(this,n))}return t.startsWith("pointer")||t.startsWith("touch")||t==="wheel"?B(()=>{e.addEventListener(t,i,s)}):e.addEventListener(t,i,s),i}function Ge(t,e,r,s,i){var n={capture:s,passive:i},a=Ue(t,e,r,n);(e===document.body||e===window||e===document||e instanceof HTMLMediaElement)&&J(()=>{e.removeEventListener(t,a,n)})}let G=null;function T(t){var e=this,r=e.ownerDocument,s=t.type,i=t.composedPath?.()||[],n=i[0]||t.target;G=t;var a=0,h=G===t&&t.__root;if(h){var l=i.indexOf(h);if(l!==-1&&(e===document||e===window)){t.__root=e;return}var g=i.indexOf(e);if(g===-1)return;l<=g&&(a=l)}if(n=i[a]||t.target,n!==e){K(t,"currentTarget",{configurable:!0,get(){return n||r}});var L=C,d=v;m(null),A(null);try{for(var u,o=[];n!==null;){var b=n.assignedSlot||n.parentNode||n.host||null;try{var E=n["__"+s];E!=null&&(!n.disabled||t.target===n)&&E.call(n,t)}catch(R){u?o.push(R):u=R}if(t.cancelBubble||b===e||b===null)break;n=b}if(u){for(let R of o)queueMicrotask(()=>{throw R});throw u}}finally{t.__root=e,delete t.currentTarget,m(L),A(d)}}}function Ye(t){var e=document.createElement("template");return e.innerHTML=t.replaceAll("",""),e.content}function _(t,e){var r=v;r.nodes===null&&(r.nodes={start:t,end:e,a:null,t:null})}function Xe(t,e){var r=(e&ge)!==0,s=(e&be)!==0,i,n=!t.startsWith("");return()=>{if(c)return _(f,null),f;i===void 0&&(i=Ye(n?t:""+t),r||(i=I(i)));var a=s||ve?document.importNode(i,!0):i.cloneNode(!0);if(r){var h=I(a),l=a.lastChild;_(h,l)}else _(a,a);return a}}function ze(t=""){if(!c){var e=w(t+"");return _(e,e),e}var r=f;return r.nodeType!==me&&(r.before(r=w()),N(r)),_(r,r),r}function Ze(){if(c)return _(f,null),f;var t=document.createDocumentFragment(),e=document.createComment(""),r=w();return t.append(e,r),_(e,r),t}function Je(t,e){if(c){var r=v;((r.f&ye)===0||r.nodes.end===null)&&(r.nodes.end=f),z();return}t!==null&&t.before(e)}function Ke(t,e){var r=e==null?"":typeof e=="object"?e+"":e;r!==(t.__t??=t.nodeValue)&&(t.__t=r,t.nodeValue=r+"")}function $e(t,e){return Q(t,e)}function Qe(t,e){x(),e.intro=e.intro??!1;const r=e.target,s=c,i=f;try{for(var n=I(r);n&&(n.nodeType!==W||n.data!==Ee);)n=Te(n);if(!n)throw P;O(!0),N(n);const a=Q(t,{...e,anchor:n});return O(!1),a}catch(a){if(a instanceof Error&&a.message.split(` -`).some(h=>h.startsWith("https://svelte.dev/e/")))throw a;return a!==P&&console.warn("Failed to hydrate: ",a),e.recover===!1&&we(),x(),Ne(r),O(!1),$e(t,e)}finally{O(s),N(i)}}const y=new Map;function Q(t,{target:e,anchor:r,props:s={},events:i,context:n,intro:a=!0}){x();var h=new Set,l=d=>{for(var u=0;u{var d=r??e.appendChild(w());return ke(d,{pending:()=>{}},u=>{if(n){Oe({});var o=Z;o.c=n}if(i&&(s.$$events=i),c&&_(u,null),g=t(u,s)||{},c&&(v.nodes.end=f,f===null||f.nodeType!==W||f.data!==De))throw Ae(),P;n&&Le()}),()=>{for(var u of h){e.removeEventListener(u,T);var o=y.get(u);--o===0?(document.removeEventListener(u,T),y.delete(u)):y.set(u,o)}q.delete(l),d!==r&&d.parentNode?.removeChild(d)}});return k.set(g,L),g}let k=new WeakMap;function et(t,e){const r=k.get(t);return r?(k.delete(t),r(e)):Promise.resolve()}let D=!1,H=Symbol();function tt(t,e,r){const s=r[e]??={store:null,source:Fe(void 0),unsubscribe:j};if(s.store!==t&&!(H in r))if(s.unsubscribe(),s.store=t??null,t==null)s.source.v=void 0,s.unsubscribe=j;else{var i=!0;s.unsubscribe=Me(t,n=>{i?s.source.v=n:Ie(s.source,n)}),i=!1}return t&&H in r?Ce(t):V(s.source)}function rt(){const t={};function e(){J(()=>{for(var r in t)t[r].unsubscribe();K(t,H,{enumerable:!1,value:!0})})}return[t,e]}function nt(t){var e=D;try{return D=!1,[t(),D]}finally{D=e}}const je="5";typeof window<"u"&&((window.__svelte??={}).v??=new Set).add(je);export{Je as a,Ke as b,tt as c,nt as d,Ge as e,Xe as f,Ze as g,Qe as h,$e as m,rt as s,ze as t,et as u}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CqZim_6h.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/CqZim_6h.js deleted file mode 100644 index f50db26..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CqZim_6h.js +++ /dev/null @@ -1 +0,0 @@ -import{l as a,u as i,b as t,d as _,e as l,i as m}from"./CQO205-B.js";function p(e){t===null&&a(),_&&t.l!==null?d(t).m.push(e):i(()=>{const n=l(e);if(typeof n=="function")return n})}function x(e){t===null&&a(),p(()=>()=>l(e))}function v(e,n,{bubbles:o=!1,cancelable:s=!1}={}){return new CustomEvent(e,{detail:n,bubbles:o,cancelable:s})}function y(){const e=t;return e===null&&a(),(n,o,s)=>{const c=e.s.$$events?.[n];if(c){const r=m(c)?c.slice():[c],u=v(n,o,s);for(const f of r)f.call(e.x,u);return!u.defaultPrevented}return!0}}function d(e){var n=e.l;return n.u??={a:[],b:[],m:[]}}export{x as a,y as c,p as o}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CsANhQOh.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/CsANhQOh.js deleted file mode 100644 index 63f5701..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/chunks/CsANhQOh.js +++ /dev/null @@ -1 +0,0 @@ -import{v as H,w as W,x as O,h as R,y as Z,z as y,j as V,A as j,B as ee,H as ne,C as Y,D as k,E as D,F as re,G as fe,I as q,J as ae,K as m,L as F,M as ie,N as B,m as se,O as $,i as le,P as oe,Q as te,R as ue,S as X,T as G,U as z,V as de,W as ve,X as ce,Y as J,Z as pe,_ as ge,$ as he}from"./CQO205-B.js";function Se(e,r){return r}function _e(e,r,f){for(var t=[],g=r.length,o,l=r.length,p=0;p{if(o){if(o.pending.delete(_),o.done.add(_),o.pending.size===0){var u=e.outrogroups;L($(o.done)),u.delete(o),u.size===0&&(e.outrogroups=null)}}else l-=1},!1)}if(l===0){var i=t.length===0&&f!==null;if(i){var d=f,a=d.parentNode;ve(a),a.append(d),e.items.clear()}L(r,!i)}else o={pending:new Set(r),done:new Set},(e.outrogroups??=new Set).add(o)}function L(e,r=!0){for(var f=0;f{var s=f();return le(s)?s:s==null?[]:$(s)}),u,c=!0;function A(){n.fallback=a,Ee(n,u,l,r,t),a!==null&&(u.length===0?(a.f&m)===0?X(a):(a.f^=m,b(a,null,l)):G(a,()=>{a=null}))}var C=W(()=>{u=V(_);var s=u.length;let I=!1;if(R){var x=ee(l)===ne;x!==(s===0)&&(l=Y(),O(l),k(!1),I=!0)}for(var E=new Set,S=ae,N=ie(),h=0;ho(l)):(a=F(()=>o(U??=H())),a.f|=m)),R&&s>0&&O(Y()),!c)if(N){for(const[P,Q]of p)E.has(P)||S.skipped_effects.add(Q.e);S.oncommit(A),S.ondiscard(()=>{})}else A();I&&k(!0),V(_)}),n={effect:C,items:p,outrogroups:null,fallback:a};c=!1,R&&(l=D)}function Ee(e,r,f,t,g){var o=(t&ge)!==0,l=r.length,p=e.items,i=e.effect.first,d,a=null,_,u=[],c=[],A,C,n,s;if(o)for(s=0;s0){var M=(t&J)!==0&&l===0?f:null;if(o){for(s=0;s{if(_!==void 0)for(n of _)n.nodes?.a?.apply()})}function me(e,r,f,t,g,o,l,p){var i=(l&oe)!==0?(l&te)===0?se(f,!1,!1):B(f):null,d=(l&ue)!==0?B(g):null;return{v:i,i:d,e:F(()=>(o(r,i??f,d??g,p),()=>{e.delete(t)}))}}function b(e,r,f){if(e.nodes)for(var t=e.nodes.start,g=e.nodes.end,o=r&&(r.f&m)===0?r.nodes.start:f;t!==null;){var l=de(t);if(o.before(t),t===g)return;t=l}}function T(e,r,f){r===null?e.effect.first=f:r.next=f,f===null?e.effect.last=r:f.prev=r}const K=he([]);function Ce(e,r="info",f=3e3){const t=Math.random().toString(36).substr(2,9);console.log(`[toasts.addToast][Action] Adding toast context={{'id': '${t}', 'type': '${r}', 'message': '${e}'}}`),K.update(g=>[...g,{id:t,message:e,type:r}]),setTimeout(()=>Te(t),f)}function Te(e){console.log(`[toasts.removeToast][Action] Removing toast context={{'id': '${e}'}}`),K.update(r=>r.filter(f=>f.id!==e))}export{Ce as a,we as e,Se as i,K as t}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/chunks/DKg_yD9X.js b/frontend/.svelte-kit/output/client/_app/immutable/chunks/DKg_yD9X.js deleted file mode 100644 index eece145..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/chunks/DKg_yD9X.js +++ /dev/null @@ -1 +0,0 @@ -import{h as i}from"./CQO205-B.js";function n(s,l,r){var t=s==null?"":""+s;return t===""?null:t}function u(s,l,r,t,f,c){var a=s.__className;if(i||a!==r||a===void 0){var e=n(r);(!i||e!==s.getAttribute("class"))&&(e==null?s.removeAttribute("class"):s.className=e),s.__className=r}return c}export{u as s}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/entry/app.B-xBk5-0.js b/frontend/.svelte-kit/output/client/_app/immutable/entry/app.B-xBk5-0.js deleted file mode 100644 index 24ed7c7..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/entry/app.B-xBk5-0.js +++ /dev/null @@ -1,2 +0,0 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["../nodes/0.Cd4CVt-Z.js","../chunks/CWb4Vnhz.js","../chunks/CQO205-B.js","../chunks/CCsGeFPC.js","../chunks/DKg_yD9X.js","../chunks/BEiADdeo.js","../chunks/CHnJS4Dz.js","../chunks/CqZim_6h.js","../chunks/CsANhQOh.js","../nodes/1.CppBCq8O.js","../nodes/2.DbjHrap6.js","../chunks/BGnnHgKo.js","../chunks/C98uKxzC.js","../nodes/3.BgpIj6zk.js"])))=>i.map(i=>d[i]); -import{h as U,z as Y,w as G,af as W,ax as Z,ac as H,e as J,Z as K,ao as Q,o as x,ap as X,j as d,ay as $,az as tt,m as et,p as rt,a0 as st,u as at,aA as S,ab as nt,at as k,s as ot,a as ct,c as it,r as ut,av as A,t as lt}from"../chunks/CQO205-B.js";import{h as ft,m as dt,u as mt,f as D,a as b,g as L,t as ht,b as _t}from"../chunks/CWb4Vnhz.js";import{o as vt}from"../chunks/CqZim_6h.js";import{B as gt,p as T,i as j}from"../chunks/C98uKxzC.js";function p(s,t,a){U&&Y();var i=new gt(s);G(()=>{var n=t()??null;i.ensure(n,n&&(e=>a(e,n)))},W)}function N(s,t){return s===t||s?.[Q]===t}function C(s={},t,a,i){return Z(()=>{var n,e;return H(()=>{n=e,e=[],J(()=>{s!==a(...e)&&(t(s,...e),n&&N(a(...n),s)&&t(null,...n))})}),()=>{K(()=>{e&&N(a(...e),s)&&t(null,...e)})}}),s}function yt(s){return class extends bt{constructor(t){super({component:s,...t})}}}class bt{#e;#t;constructor(t){var a=new Map,i=(e,r)=>{var o=et(r,!1,!1);return a.set(e,o),o};const n=new Proxy({...t.props||{},$$events:{}},{get(e,r){return d(a.get(r)??i(r,Reflect.get(e,r)))},has(e,r){return r===X?!0:(d(a.get(r)??i(r,Reflect.get(e,r))),Reflect.has(e,r))},set(e,r,o){return x(a.get(r)??i(r,o),o),Reflect.set(e,r,o)}});this.#t=(t.hydrate?ft:dt)(t.component,{target:t.target,anchor:t.anchor,props:n,context:t.context,intro:t.intro??!1,recover:t.recover}),(!t?.props?.$$host||t.sync===!1)&&$(),this.#e=n.$$events;for(const e of Object.keys(this.#t))e==="$set"||e==="$destroy"||e==="$on"||tt(this,e,{get(){return this.#t[e]},set(r){this.#t[e]=r},enumerable:!0});this.#t.$set=e=>{Object.assign(n,e)},this.#t.$destroy=()=>{mt(this.#t)}}$set(t){this.#t.$set(t)}$on(t,a){this.#e[t]=this.#e[t]||[];const i=(...n)=>a.call(this,...n);return this.#e[t].push(i),()=>{this.#e[t]=this.#e[t].filter(n=>n!==i)}}$destroy(){this.#t.$destroy()}}const Et="modulepreload",Pt=function(s,t){return new URL(s,t).href},B={},O=function(t,a,i){let n=Promise.resolve();if(a&&a.length>0){let R=function(u){return Promise.all(u.map(f=>Promise.resolve(f).then(m=>({status:"fulfilled",value:m}),m=>({status:"rejected",reason:m}))))};const r=document.getElementsByTagName("link"),o=document.querySelector("meta[property=csp-nonce]"),w=o?.nonce||o?.getAttribute("nonce");n=R(a.map(u=>{if(u=Pt(u,i),u in B)return;B[u]=!0;const f=u.endsWith(".css"),m=f?'[rel="stylesheet"]':"";if(i)for(let h=r.length-1;h>=0;h--){const c=r[h];if(c.href===u&&(!f||c.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${u}"]${m}`))return;const l=document.createElement("link");if(l.rel=f?"stylesheet":Et,f||(l.as="script"),l.crossOrigin="",l.href=u,w&&l.setAttribute("nonce",w),document.head.appendChild(l),f)return new Promise((h,c)=>{l.addEventListener("load",h),l.addEventListener("error",()=>c(new Error(`Unable to preload CSS for ${u}`)))})}))}function e(r){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=r,window.dispatchEvent(o),!o.defaultPrevented)throw r}return n.then(r=>{for(const o of r||[])o.status==="rejected"&&e(o.reason);return t().catch(e)})},jt={};var wt=D('
'),Rt=D(" ",1);function kt(s,t){rt(t,!0);let a=T(t,"components",23,()=>[]),i=T(t,"data_0",3,null),n=T(t,"data_1",3,null);st(()=>t.stores.page.set(t.page)),at(()=>{t.stores,t.page,t.constructors,a(),t.form,i(),n(),t.stores.page.notify()});let e=S(!1),r=S(!1),o=S(null);vt(()=>{const c=t.stores.page.subscribe(()=>{d(e)&&(x(r,!0),nt().then(()=>{x(o,document.title||"untitled page",!0)}))});return x(e,!0),c});const w=A(()=>t.constructors[1]);var R=Rt(),u=k(R);{var f=c=>{const _=A(()=>t.constructors[0]);var v=L(),E=k(v);p(E,()=>d(_),(g,y)=>{C(y(g,{get data(){return i()},get form(){return t.form},get params(){return t.page.params},children:(P,xt)=>{var M=L(),V=k(M);p(V,()=>d(w),(q,z)=>{C(z(q,{get data(){return n()},get form(){return t.form},get params(){return t.page.params}}),F=>a()[1]=F,()=>a()?.[1])}),b(P,M)},$$slots:{default:!0}}),P=>a()[0]=P,()=>a()?.[0])}),b(c,v)},m=c=>{const _=A(()=>t.constructors[0]);var v=L(),E=k(v);p(E,()=>d(_),(g,y)=>{C(y(g,{get data(){return i()},get form(){return t.form},get params(){return t.page.params}}),P=>a()[0]=P,()=>a()?.[0])}),b(c,v)};j(u,c=>{t.constructors[1]?c(f):c(m,!1)})}var l=ot(u,2);{var h=c=>{var _=wt(),v=it(_);{var E=g=>{var y=ht();lt(()=>_t(y,d(o))),b(g,y)};j(v,g=>{d(r)&&g(E)})}ut(_),b(c,_)};j(l,c=>{d(e)&&c(h)})}b(s,R),ct()}const pt=yt(kt),Ct=[()=>O(()=>import("../nodes/0.Cd4CVt-Z.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8]),import.meta.url),()=>O(()=>import("../nodes/1.CppBCq8O.js"),__vite__mapDeps([9,1,2,3,5,6,7]),import.meta.url),()=>O(()=>import("../nodes/2.DbjHrap6.js"),__vite__mapDeps([10,11,2,8,1,3,12,7,4]),import.meta.url),()=>O(()=>import("../nodes/3.BgpIj6zk.js"),__vite__mapDeps([13,11,2,8,1,3,12]),import.meta.url)],Mt=[],Nt={"/":[2],"/settings":[3]},I={handleError:(({error:s})=>{console.error(s)}),reroute:(()=>{}),transport:{}},Ot=Object.fromEntries(Object.entries(I.transport).map(([s,t])=>[s,t.decode])),Bt=Object.fromEntries(Object.entries(I.transport).map(([s,t])=>[s,t.encode])),Dt=!1,It=(s,t)=>Ot[s](t);export{It as decode,Ot as decoders,Nt as dictionary,Bt as encoders,Dt as hash,I as hooks,jt as matchers,Ct as nodes,pt as root,Mt as server_loads}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/entry/start.CiUb2lZD.js b/frontend/.svelte-kit/output/client/_app/immutable/entry/start.CiUb2lZD.js deleted file mode 100644 index 1e6a22b..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/entry/start.CiUb2lZD.js +++ /dev/null @@ -1 +0,0 @@ -import{l as o,a as r}from"../chunks/CHnJS4Dz.js";export{o as load_css,r as start}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/0.Cd4CVt-Z.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/0.Cd4CVt-Z.js deleted file mode 100644 index 02647b1..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/nodes/0.Cd4CVt-Z.js +++ /dev/null @@ -1,5 +0,0 @@ -import{f as u,a as c,s as b,c as g,b as x}from"../chunks/CWb4Vnhz.js";import{i as _}from"../chunks/CCsGeFPC.js";import{h as $,z as y,p as w,t as h,a as S,s as d,c as v,r as l,j as p,at as j}from"../chunks/CQO205-B.js";import{s as m}from"../chunks/DKg_yD9X.js";import{p as T}from"../chunks/BEiADdeo.js";import{e as z,t as O}from"../chunks/CsANhQOh.js";function k(r,a,s,o,n){$&&y();var e=a.$$slots?.[s],t=!1;e===!0&&(e=a.children,t=!0),e===void 0||e(r,t?()=>o:o)}const A=!1,D=!1,Q=Object.freeze(Object.defineProperty({__proto__:null,prerender:D,ssr:A},Symbol.toStringTag,{value:"Module"}));var F=u('
Superset Tools
');function M(r,a){w(a,!1);const s=()=>g(T,"$page",o),[o,n]=b();_();var e=F(),t=d(v(e),2),i=v(t),f=d(i,2);l(t),l(e),h(()=>{m(i,1,`text-gray-600 hover:text-blue-600 font-medium ${s().url.pathname==="/"?"text-blue-600 border-b-2 border-blue-600":""}`),m(f,1,`text-gray-600 hover:text-blue-600 font-medium ${s().url.pathname==="/settings"?"text-blue-600 border-b-2 border-blue-600":""}`)}),c(r,e),S(),n()}var N=u('
© 2025 Superset Tools. All rights reserved.
');function P(r){var a=N();c(r,a)}var q=u("
"),B=u('
');function C(r){const a=()=>g(O,"$toasts",s),[s,o]=b();var n=B();z(n,5,a,e=>e.id,(e,t)=>{var i=q(),f=v(i,!0);l(i),h(()=>{m(i,1,`p-4 rounded-md shadow-lg text-white - ${p(t).type==="info"&&"bg-blue-500"} - ${p(t).type==="success"&&"bg-green-500"} - ${p(t).type==="error"&&"bg-red-500"} - `),x(f,p(t).message)}),c(e,i)}),l(n),c(r,n),o()}var E=u('
',1);function R(r,a){var s=E(),o=j(s);C(o);var n=d(o,2),e=v(n);M(e,{});var t=d(e,2),i=v(t);k(i,a,"default",{}),l(t);var f=d(t,2);P(f),l(n),c(r,s)}export{R as component,Q as universal}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/1.CppBCq8O.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/1.CppBCq8O.js deleted file mode 100644 index 544fb9e..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/nodes/1.CppBCq8O.js +++ /dev/null @@ -1 +0,0 @@ -import{f,a as g,s as u,b as p,c as b}from"../chunks/CWb4Vnhz.js";import{i as d}from"../chunks/CCsGeFPC.js";import{p as h,t as v,a as _,c as e,r as s,s as $,n as y}from"../chunks/CQO205-B.js";import{p as k}from"../chunks/BEiADdeo.js";var w=f('');function q(n,i){h(i,!1);const r=()=>b(k,"$page",c),[c,l]=u();d();var t=w(),a=e(t),m=e(a,!0);s(a);var o=$(a,2),x=e(o,!0);s(o),y(2),s(t),v(()=>{p(m,r().status),p(x,r().error?.message||"Page not found")}),g(n,t),_(),l()}export{q as component}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/2.DbjHrap6.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/2.DbjHrap6.js deleted file mode 100644 index eb7f892..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/nodes/2.DbjHrap6.js +++ /dev/null @@ -1 +0,0 @@ -import{a as de,s as z,r as ee,b as le,c as fe}from"../chunks/BGnnHgKo.js";import{f as m,c as Q,a as i,s as ve,b as F,e as J,g as ae}from"../chunks/CWb4Vnhz.js";import{i as re}from"../chunks/CCsGeFPC.js";import{$ as V,p as oe,au as pe,c as u,r as c,a as se,at as E,s as y,t as O,j as e,k as B,e as p,q as I,m as ge,av as be,n as _e,aw as he,f as ke,g as xe}from"../chunks/CQO205-B.js";import{i as P,p as ue}from"../chunks/C98uKxzC.js";import{e as ne,i as ie}from"../chunks/CsANhQOh.js";import{o as ye,a as $e,c as we}from"../chunks/CqZim_6h.js";import{s as Te}from"../chunks/DKg_yD9X.js";function Se($){return function(...w){var d=w[0];return d.preventDefault(),$?.apply(this,w)}}async function De(){try{return{plugins:await de.getPlugins()}}catch($){return console.error("Failed to load plugins:",$),{plugins:[],error:"Failed to load plugins"}}}const et=Object.freeze(Object.defineProperty({__proto__:null,load:De},Symbol.toStringTag,{value:"Module"})),ce=V([]),H=V(null),U=V(null),te=V([]);var Fe=m('
'),Re=m('

',1),Ae=m("

No task selected.

"),Oe=m('
');function Ce($,w){oe(w,!1);const d=()=>Q(U,"$selectedTask",L),a=()=>Q(te,"$taskLogs",L),[L,K]=ve();let s;ye(()=>{const f=pe(U);if(f){console.log(`[TaskRunner][Entry] Connecting to logs for task: ${f.id}`),te.set([]);const n=`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/ws/logs/${f.id}`;s=new WebSocket(n),s.onopen=()=>{console.log("[TaskRunner][Coherence:OK] WebSocket connection established")},s.onmessage=g=>{const v=JSON.parse(g.data);te.update(t=>[...t,v])},s.onerror=g=>{console.error("[TaskRunner][Coherence:Failed] WebSocket error:",g)},s.onclose=()=>{console.log("[TaskRunner][Exit] WebSocket connection closed")}}}),$e(()=>{s&&(console.log("[TaskRunner][Action] Closing WebSocket connection."),s.close())}),re();var k=Oe(),M=u(k);{var W=f=>{var R=Re(),n=E(R),g=u(n);c(n);var v=y(n,2);ne(v,5,a,ie,(t,o)=>{var b=Fe(),_=u(b),S=u(_,!0);c(_);var D=y(_,2),A=u(D);c(D);var h=y(D,2),r=u(h,!0);c(h),c(b),O(l=>{F(S,l),Te(D,1,e(o).level==="ERROR"?"text-red-500":"text-green-400"),F(A,`[${e(o).level??""}]`),F(r,e(o).message)},[()=>new Date(e(o).timestamp).toLocaleTimeString()]),i(t,b)}),c(v),O(()=>F(g,`Task: ${d().plugin_id??""}`)),i(f,R)},T=f=>{var R=Ae();i(f,R)};P(M,f=>{d()?f(W):f(T,!1)})}c(k),i($,k),se(),K()}var Ee=m(''),Pe=m(''),Le=m(''),We=m('
'),je=m(' ',1),ze=m('
');function Be($,w){oe(w,!1);let d=ue(w,"schema",8),a=ge({});const L=we();function K(){console.log("[DynamicForm][Action] Submitting form data.",{formData:e(a)}),L("submit",e(a))}function s(){if(d()&&d().properties)for(const T in d().properties)I(a,e(a)[T]=d().properties[T].default||"")}s(),re();var k=ze(),M=u(k);{var W=T=>{var f=je(),R=E(f);ne(R,1,()=>(B(d()),p(()=>Object.entries(d().properties))),ie,(n,g)=>{var v=be(()=>he(e(g),2));let t=()=>e(v)[0],o=()=>e(v)[1];var b=We(),_=u(b),S=u(_,!0);c(_);var D=y(_,2);{var A=r=>{var l=Ee();ee(l),O(()=>{z(l,"id",t()),z(l,"placeholder",(o(),p(()=>o().description||"")))}),le(l,()=>e(a)[t()],j=>I(a,e(a)[t()]=j)),i(r,l)},h=r=>{var l=ae(),j=E(l);{var X=C=>{var x=Pe();ee(x),O(()=>{z(x,"id",t()),z(x,"placeholder",(o(),p(()=>o().description||"")))}),le(x,()=>e(a)[t()],q=>I(a,e(a)[t()]=q)),i(C,x)},N=C=>{var x=ae(),q=E(x);{var Y=Z=>{var G=Le();ee(G),O(()=>z(G,"id",t())),fe(G,()=>e(a)[t()],me=>I(a,e(a)[t()]=me)),i(Z,G)};P(q,Z=>{o(),p(()=>o().type==="boolean")&&Z(Y)},!0)}i(C,x)};P(j,C=>{o(),p(()=>o().type==="number"||o().type==="integer")?C(X):C(N,!1)},!0)}i(r,l)};P(D,r=>{o(),p(()=>o().type==="string")?r(A):r(h,!1)})}c(b),O(()=>{z(_,"for",t()),F(S,(o(),t(),p(()=>o().title||t())))}),i(n,b)}),_e(2),i(T,f)};P(M,T=>{B(d()),p(()=>d()&&d().properties)&&T(W)})}c(k),J("submit",k,Se(K)),i($,k),se()}var Ke=m(' ',1),Me=m('

',1),Ne=m('
'),qe=m('

'),He=m('

Available Tools

',1),Je=m('
');function tt($,w){oe(w,!1);const d=()=>Q(U,"$selectedTask",L),a=()=>Q(H,"$selectedPlugin",L),[L,K]=ve();let s=ue(w,"data",8);function k(n){console.log(`[Dashboard][Action] Selecting plugin: ${n.id}`),H.set(n)}async function M(n){console.log("[App.handleFormSubmit][Action] Handling form submission for task creation.");const g=n.detail;try{const v=pe(H),t=await de.createTask(v.id,g);U.set(t),H.set(null),console.log(`[App.handleFormSubmit][Coherence:OK] Task created id=${t.id}`)}catch(v){console.error(`[App.handleFormSubmit][Coherence:Failed] Task creation failed error=${v}`)}}ke(()=>(B(s()),ce),()=>{s().plugins&&ce.set(s().plugins)}),xe(),re();var W=Je(),T=u(W);{var f=n=>{var g=Ke(),v=E(g);Ce(v,{});var t=y(v,2);J("click",t,()=>U.set(null)),i(n,g)},R=n=>{var g=ae(),v=E(g);{var t=b=>{var _=Me(),S=E(_),D=u(S,!0);c(S);var A=y(S,2);Be(A,{get schema(){return a(),p(()=>a().schema)},$$events:{submit:M}});var h=y(A,2);O(()=>F(D,(a(),p(()=>a().name)))),J("click",h,()=>H.set(null)),i(b,_)},o=b=>{var _=He(),S=y(E(_),2);{var D=h=>{var r=Ne(),l=u(r,!0);c(r),O(()=>F(l,(B(s()),p(()=>s().error)))),i(h,r)};P(S,h=>{B(s()),p(()=>s().error)&&h(D)})}var A=y(S,2);ne(A,5,()=>(B(s()),p(()=>s().plugins)),ie,(h,r)=>{var l=qe(),j=u(l),X=u(j,!0);c(j);var N=y(j,2),C=u(N,!0);c(N);var x=y(N,2),q=u(x);c(x),c(l),O(()=>{F(X,(e(r),p(()=>e(r).name))),F(C,(e(r),p(()=>e(r).description))),F(q,`v${e(r),p(()=>e(r).version)??""}`)}),J("click",l,()=>k(e(r))),J("keydown",l,Y=>Y.key==="Enter"&&k(e(r))),i(h,l)}),c(A),i(b,_)};P(v,b=>{a()?b(t):b(o,!1)},!0)}i(n,g)};P(T,n=>{d()?n(f):n(R,!1)})}c(W),i($,W),se(),K()}export{tt as component,et as universal}; diff --git a/frontend/.svelte-kit/output/client/_app/immutable/nodes/3.BgpIj6zk.js b/frontend/.svelte-kit/output/client/_app/immutable/nodes/3.BgpIj6zk.js deleted file mode 100644 index 04d2afd..0000000 --- a/frontend/.svelte-kit/output/client/_app/immutable/nodes/3.BgpIj6zk.js +++ /dev/null @@ -1 +0,0 @@ -import{a as Ce,b as g,c as Fe,r as u,u as Ae,d as Oe,e as Ue,t as De,f as Ge}from"../chunks/BGnnHgKo.js";import{f as _,e as b,a as h,b as p}from"../chunks/CWb4Vnhz.js";import{i as Te}from"../chunks/CCsGeFPC.js";import{p as $e,m as I,f as Ke,g as Ne,t as L,j as t,a as je,k as R,s as a,c as s,o as x,e as c,r as n,n as Pe,q as m}from"../chunks/CQO205-B.js";import{p as Ie,i as Y}from"../chunks/C98uKxzC.js";import{e as Le,i as Re,a as d}from"../chunks/CsANhQOh.js";async function Ye(){try{return{settings:await Ce.getSettings()}}catch(y){return console.error("Failed to load settings:",y),{settings:{environments:[],settings:{backup_path:"",default_environment_id:null}},error:"Failed to load settings"}}}const et=Object.freeze(Object.defineProperty({__proto__:null,load:Ye},Symbol.toStringTag,{value:"Module"}));var qe=_('
'),ze=_('

Warning

No Superset environments configured. You must add at least one environment to perform backups or migrations.

'),Be=_(' '),Me=_(''),We=_('

Settings

Global Settings

Superset Environments

NameURLUsernameDefaultActions

');function tt(y,q){$e(q,!1);let v=Ie(q,"data",8),i=I(v().settings),o=I({id:"",name:"",url:"",username:"",password:"",is_default:!1}),l=I(null);async function le(){try{console.log("[Settings.handleSaveGlobal][Action] Saving global settings."),await Ae(t(i).settings),d("Global settings saved","success"),console.log("[Settings.handleSaveGlobal][Coherence:OK] Global settings saved.")}catch(e){console.error("[Settings.handleSaveGlobal][Coherence:Failed] Failed to save global settings:",e),d("Failed to save global settings","error")}}async function ce(){try{console.log(`[Settings.handleAddOrUpdateEnv][Action] ${t(l)?"Updating":"Adding"} environment.`),t(l)?(await Oe(t(l),t(o)),d("Environment updated","success")):(await Ue(t(o)),d("Environment added","success")),z(),location.reload(),console.log("[Settings.handleAddOrUpdateEnv][Coherence:OK] Environment saved.")}catch(e){console.error("[Settings.handleAddOrUpdateEnv][Coherence:Failed] Failed to save environment:",e),d("Failed to save environment","error")}}async function ve(e){if(confirm("Are you sure you want to delete this environment?"))try{console.log(`[Settings.handleDeleteEnv][Action] Deleting environment: ${e}`),await Ge(e),d("Environment deleted","success"),location.reload(),console.log("[Settings.handleDeleteEnv][Coherence:OK] Environment deleted.")}catch(r){console.error("[Settings.handleDeleteEnv][Coherence:Failed] Failed to delete environment:",r),d("Failed to delete environment","error")}}async function ue(e){try{console.log(`[Settings.handleTestEnv][Action] Testing environment: ${e}`);const r=await De(e);r.status==="success"?(d("Connection successful","success"),console.log("[Settings.handleTestEnv][Coherence:OK] Connection successful.")):(d(`Connection failed: ${r.message}`,"error"),console.log("[Settings.handleTestEnv][Coherence:Failed] Connection failed."))}catch(r){console.error("[Settings.handleTestEnv][Coherence:Failed] Error testing connection:",r),d("Failed to test connection","error")}}function pe(e){x(o,{...e}),x(l,e.id)}function z(){x(o,{id:"",name:"",url:"",username:"",password:"",is_default:!1}),x(l,null)}Ke(()=>R(v()),()=>{x(i,v().settings)}),Ne(),Te();var k=We(),B=a(s(k),2);{var me=e=>{var r=qe(),f=s(r,!0);n(r),L(()=>p(f,(R(v()),c(()=>v().error)))),h(e,r)};Y(B,e=>{R(v()),c(()=>v().error)&&e(me)})}var E=a(B,2),M=a(s(E),2),S=s(M),W=a(s(S),2);u(W),n(S);var ge=a(S,2);n(M),n(E);var H=a(E,2),J=a(s(H),2);{var be=e=>{var r=ze();h(e,r)};Y(J,e=>{t(i),c(()=>t(i).environments.length===0)&&e(be)})}var C=a(J,2),Q=s(C),V=a(s(Q));Le(V,5,()=>(t(i),c(()=>t(i).environments)),Re,(e,r)=>{var f=Be(),K=s(f),ye=s(K,!0);n(K);var N=a(K),we=s(N,!0);n(N);var j=a(N),ke=s(j,!0);n(j);var P=a(j),Ee=s(P,!0);n(P);var oe=a(P),de=s(oe),ie=a(de,2),Se=a(ie,2);n(oe),n(f),L(()=>{p(ye,(t(r),c(()=>t(r).name))),p(we,(t(r),c(()=>t(r).url))),p(ke,(t(r),c(()=>t(r).username))),p(Ee,(t(r),c(()=>t(r).is_default?"Yes":"No")))}),b("click",de,()=>ue(t(r).id)),b("click",ie,()=>pe(t(r))),b("click",Se,()=>ve(t(r).id)),h(e,f)}),n(V),n(Q),n(C);var X=a(C,2),F=s(X),fe=s(F);n(F);var A=a(F,2),O=s(A),U=a(s(O),2);u(U),n(O);var D=a(O,2),Z=a(s(D),2);u(Z),n(D);var G=a(D,2),ee=a(s(G),2);u(ee),n(G);var T=a(G,2),te=a(s(T),2);u(te),n(T);var $=a(T,2),ae=a(s($),2);u(ae),n($);var re=a($,2),ne=s(re);u(ne),Pe(2),n(re),n(A);var se=a(A,2),w=s(se),he=s(w);n(w);var xe=a(w,2);{var _e=e=>{var r=Me();b("click",r,z),h(e,r)};Y(xe,e=>{t(l)&&e(_e)})}n(se),n(X),n(H),n(k),L(()=>{p(fe,`${t(l)?"Edit":"Add"} Environment`),U.disabled=!!t(l),p(he,`${t(l)?"Update":"Add"} Environment`)}),g(W,()=>t(i).settings.backup_path,e=>m(i,t(i).settings.backup_path=e)),b("click",ge,le),g(U,()=>t(o).id,e=>m(o,t(o).id=e)),g(Z,()=>t(o).name,e=>m(o,t(o).name=e)),g(ee,()=>t(o).url,e=>m(o,t(o).url=e)),g(te,()=>t(o).username,e=>m(o,t(o).username=e)),g(ae,()=>t(o).password,e=>m(o,t(o).password=e)),Fe(ne,()=>t(o).is_default,e=>m(o,t(o).is_default=e)),b("click",w,ce),h(y,k),je()}export{tt as component,et as universal}; diff --git a/frontend/.svelte-kit/output/client/_app/version.json b/frontend/.svelte-kit/output/client/_app/version.json index 1fb0742..f940266 100644 --- a/frontend/.svelte-kit/output/client/_app/version.json +++ b/frontend/.svelte-kit/output/client/_app/version.json @@ -1 +1 @@ -{"version":"1766259433446"} \ No newline at end of file +{"version":"1766262590857"} \ No newline at end of file diff --git a/frontend/.svelte-kit/output/prerendered/dependencies/_app/env.js b/frontend/.svelte-kit/output/prerendered/dependencies/_app/env.js index f5427da..7432e14 100644 --- a/frontend/.svelte-kit/output/prerendered/dependencies/_app/env.js +++ b/frontend/.svelte-kit/output/prerendered/dependencies/_app/env.js @@ -1 +1 @@ -export const env={} \ No newline at end of file +export const env={"PUBLIC_WS_URL":"ws://localhost:8000"} \ No newline at end of file diff --git a/frontend/.svelte-kit/output/server/.vite/manifest.json b/frontend/.svelte-kit/output/server/.vite/manifest.json index 53586a9..0a91f23 100644 --- a/frontend/.svelte-kit/output/server/.vite/manifest.json +++ b/frontend/.svelte-kit/output/server/.vite/manifest.json @@ -129,6 +129,9 @@ "_index2.js", "_stores.js", "_toasts.js" + ], + "css": [ + "_app/immutable/assets/_layout.RZHRvmcL.css" ] }, "src/routes/+layout.ts": { diff --git a/frontend/.svelte-kit/output/server/chunks/internal.js b/frontend/.svelte-kit/output/server/chunks/internal.js index 7cb3f4a..06b5acd 100644 --- a/frontend/.svelte-kit/output/server/chunks/internal.js +++ b/frontend/.svelte-kit/output/server/chunks/internal.js @@ -950,7 +950,7 @@ const options = {
` + status + '\n
\n

' + message + "

\n
\n
\n \n\n" }, - version_hash: "1uq6ubj" + version_hash: "1ootf77" }; async function get_hooks() { let handle; diff --git a/frontend/.svelte-kit/output/server/manifest-full.js b/frontend/.svelte-kit/output/server/manifest-full.js index 96106fc..53133d6 100644 --- a/frontend/.svelte-kit/output/server/manifest-full.js +++ b/frontend/.svelte-kit/output/server/manifest-full.js @@ -10,7 +10,7 @@ return { assets: new Set([]), mimeTypes: {}, _: { - client: {start:"_app/immutable/entry/start.CiUb2lZD.js",app:"_app/immutable/entry/app.B-xBk5-0.js",imports:["_app/immutable/entry/start.CiUb2lZD.js","_app/immutable/chunks/CHnJS4Dz.js","_app/immutable/chunks/CQO205-B.js","_app/immutable/chunks/CqZim_6h.js","_app/immutable/entry/app.B-xBk5-0.js","_app/immutable/chunks/CQO205-B.js","_app/immutable/chunks/CWb4Vnhz.js","_app/immutable/chunks/CqZim_6h.js","_app/immutable/chunks/C98uKxzC.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false}, + client: {start:"_app/immutable/entry/start.BHAeOrfR.js",app:"_app/immutable/entry/app.BXnpILpp.js",imports:["_app/immutable/entry/start.BHAeOrfR.js","_app/immutable/chunks/D0iaTcAo.js","_app/immutable/chunks/BtL0wB3H.js","_app/immutable/chunks/BxZpmA7Z.js","_app/immutable/entry/app.BXnpILpp.js","_app/immutable/chunks/BtL0wB3H.js","_app/immutable/chunks/cv2LK44M.js","_app/immutable/chunks/BxZpmA7Z.js","_app/immutable/chunks/vVxDbqKK.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false}, nodes: [ __memo(() => import('./nodes/0.js')), __memo(() => import('./nodes/1.js')), diff --git a/frontend/.svelte-kit/output/server/manifest.js b/frontend/.svelte-kit/output/server/manifest.js index 96106fc..53133d6 100644 --- a/frontend/.svelte-kit/output/server/manifest.js +++ b/frontend/.svelte-kit/output/server/manifest.js @@ -10,7 +10,7 @@ return { assets: new Set([]), mimeTypes: {}, _: { - client: {start:"_app/immutable/entry/start.CiUb2lZD.js",app:"_app/immutable/entry/app.B-xBk5-0.js",imports:["_app/immutable/entry/start.CiUb2lZD.js","_app/immutable/chunks/CHnJS4Dz.js","_app/immutable/chunks/CQO205-B.js","_app/immutable/chunks/CqZim_6h.js","_app/immutable/entry/app.B-xBk5-0.js","_app/immutable/chunks/CQO205-B.js","_app/immutable/chunks/CWb4Vnhz.js","_app/immutable/chunks/CqZim_6h.js","_app/immutable/chunks/C98uKxzC.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false}, + client: {start:"_app/immutable/entry/start.BHAeOrfR.js",app:"_app/immutable/entry/app.BXnpILpp.js",imports:["_app/immutable/entry/start.BHAeOrfR.js","_app/immutable/chunks/D0iaTcAo.js","_app/immutable/chunks/BtL0wB3H.js","_app/immutable/chunks/BxZpmA7Z.js","_app/immutable/entry/app.BXnpILpp.js","_app/immutable/chunks/BtL0wB3H.js","_app/immutable/chunks/cv2LK44M.js","_app/immutable/chunks/BxZpmA7Z.js","_app/immutable/chunks/vVxDbqKK.js"],stylesheets:[],fonts:[],uses_env_dynamic_public:false}, nodes: [ __memo(() => import('./nodes/0.js')), __memo(() => import('./nodes/1.js')), diff --git a/frontend/.svelte-kit/output/server/nodes/0.js b/frontend/.svelte-kit/output/server/nodes/0.js index 5d17e4c..4d6d213 100644 --- a/frontend/.svelte-kit/output/server/nodes/0.js +++ b/frontend/.svelte-kit/output/server/nodes/0.js @@ -8,6 +8,6 @@ export const universal = { "prerender": false }; export const universal_id = "src/routes/+layout.ts"; -export const imports = ["_app/immutable/nodes/0.Cd4CVt-Z.js","_app/immutable/chunks/CWb4Vnhz.js","_app/immutable/chunks/CQO205-B.js","_app/immutable/chunks/CCsGeFPC.js","_app/immutable/chunks/DKg_yD9X.js","_app/immutable/chunks/BEiADdeo.js","_app/immutable/chunks/CHnJS4Dz.js","_app/immutable/chunks/CqZim_6h.js","_app/immutable/chunks/CsANhQOh.js"]; -export const stylesheets = []; +export const imports = ["_app/immutable/nodes/0.DZdF_zz-.js","_app/immutable/chunks/cv2LK44M.js","_app/immutable/chunks/BtL0wB3H.js","_app/immutable/chunks/CRLlKr96.js","_app/immutable/chunks/xdjHc-A2.js","_app/immutable/chunks/DXE57cnx.js","_app/immutable/chunks/D0iaTcAo.js","_app/immutable/chunks/BxZpmA7Z.js","_app/immutable/chunks/Dbod7Wv8.js"]; +export const stylesheets = ["_app/immutable/assets/0.RZHRvmcL.css"]; export const fonts = []; diff --git a/frontend/.svelte-kit/output/server/nodes/1.js b/frontend/.svelte-kit/output/server/nodes/1.js index fdbf274..6232bd3 100644 --- a/frontend/.svelte-kit/output/server/nodes/1.js +++ b/frontend/.svelte-kit/output/server/nodes/1.js @@ -3,6 +3,6 @@ export const index = 1; let component_cache; export const component = async () => component_cache ??= (await import('../entries/pages/_error.svelte.js')).default; -export const imports = ["_app/immutable/nodes/1.CppBCq8O.js","_app/immutable/chunks/CWb4Vnhz.js","_app/immutable/chunks/CQO205-B.js","_app/immutable/chunks/CCsGeFPC.js","_app/immutable/chunks/BEiADdeo.js","_app/immutable/chunks/CHnJS4Dz.js","_app/immutable/chunks/CqZim_6h.js"]; +export const imports = ["_app/immutable/nodes/1.Bh-fCbID.js","_app/immutable/chunks/cv2LK44M.js","_app/immutable/chunks/BtL0wB3H.js","_app/immutable/chunks/CRLlKr96.js","_app/immutable/chunks/DXE57cnx.js","_app/immutable/chunks/D0iaTcAo.js","_app/immutable/chunks/BxZpmA7Z.js"]; export const stylesheets = []; export const fonts = []; diff --git a/frontend/.svelte-kit/output/server/nodes/2.js b/frontend/.svelte-kit/output/server/nodes/2.js index fe83322..c81d2a8 100644 --- a/frontend/.svelte-kit/output/server/nodes/2.js +++ b/frontend/.svelte-kit/output/server/nodes/2.js @@ -9,6 +9,6 @@ export const universal = { "load": null }; export const universal_id = "src/routes/+page.ts"; -export const imports = ["_app/immutable/nodes/2.DbjHrap6.js","_app/immutable/chunks/BGnnHgKo.js","_app/immutable/chunks/CQO205-B.js","_app/immutable/chunks/CsANhQOh.js","_app/immutable/chunks/CWb4Vnhz.js","_app/immutable/chunks/CCsGeFPC.js","_app/immutable/chunks/C98uKxzC.js","_app/immutable/chunks/CqZim_6h.js","_app/immutable/chunks/DKg_yD9X.js"]; +export const imports = ["_app/immutable/nodes/2.BmiXdPHI.js","_app/immutable/chunks/DyPeVqDG.js","_app/immutable/chunks/BtL0wB3H.js","_app/immutable/chunks/Dbod7Wv8.js","_app/immutable/chunks/cv2LK44M.js","_app/immutable/chunks/CRLlKr96.js","_app/immutable/chunks/vVxDbqKK.js","_app/immutable/chunks/BxZpmA7Z.js","_app/immutable/chunks/xdjHc-A2.js"]; export const stylesheets = []; export const fonts = []; diff --git a/frontend/.svelte-kit/output/server/nodes/3.js b/frontend/.svelte-kit/output/server/nodes/3.js index cc0a2b6..880411c 100644 --- a/frontend/.svelte-kit/output/server/nodes/3.js +++ b/frontend/.svelte-kit/output/server/nodes/3.js @@ -9,6 +9,6 @@ export const universal = { "load": null }; export const universal_id = "src/routes/settings/+page.ts"; -export const imports = ["_app/immutable/nodes/3.BgpIj6zk.js","_app/immutable/chunks/BGnnHgKo.js","_app/immutable/chunks/CQO205-B.js","_app/immutable/chunks/CsANhQOh.js","_app/immutable/chunks/CWb4Vnhz.js","_app/immutable/chunks/CCsGeFPC.js","_app/immutable/chunks/C98uKxzC.js"]; +export const imports = ["_app/immutable/nodes/3.guWMyWpk.js","_app/immutable/chunks/DyPeVqDG.js","_app/immutable/chunks/BtL0wB3H.js","_app/immutable/chunks/Dbod7Wv8.js","_app/immutable/chunks/cv2LK44M.js","_app/immutable/chunks/CRLlKr96.js","_app/immutable/chunks/vVxDbqKK.js"]; export const stylesheets = []; export const fonts = []; diff --git a/frontend/src/components/TaskRunner.svelte b/frontend/src/components/TaskRunner.svelte index 105f32f..33d3ede 100755 --- a/frontend/src/components/TaskRunner.svelte +++ b/frontend/src/components/TaskRunner.svelte @@ -13,6 +13,7 @@ import { onMount, onDestroy } from 'svelte'; import { get } from 'svelte/store'; import { selectedTask, taskLogs } from '../lib/stores.js'; + import { getWsUrl } from '../lib/api.js'; // [/SECTION] let ws; @@ -26,8 +27,7 @@ if (task) { console.log(`[TaskRunner][Entry] Connecting to logs for task: ${task.id}`); taskLogs.set([]); // Clear previous logs - const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; - const wsUrl = `${protocol}//${window.location.host}/ws/logs/${task.id}`; + const wsUrl = getWsUrl(task.id); ws = new WebSocket(wsUrl); ws.onopen = () => { diff --git a/frontend/src/lib/api.js b/frontend/src/lib/api.js index b55b9d8..f383aef 100755 --- a/frontend/src/lib/api.js +++ b/frontend/src/lib/api.js @@ -4,9 +4,20 @@ // @LAYER: Infra-API import { addToast } from './toasts.js'; +import { PUBLIC_WS_URL } from '$env/static/public'; const API_BASE_URL = '/api'; +/** + * Returns the WebSocket URL for a specific task, with fallback logic. + * @param {string} taskId + * @returns {string} + */ +export const getWsUrl = (taskId) => { + const baseUrl = PUBLIC_WS_URL || `ws://${window.location.hostname}:8000`; + return `${baseUrl}/ws/logs/${taskId}`; +}; + // [DEF:fetchApi:Function] // @PURPOSE: Generic GET request wrapper. // @PARAM: endpoint (string) - API endpoint. diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index 2b4526b..4fd5373 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -1,4 +1,5 @@ + ``` + +2. **WebSocket Configuration**: + - Create/Update `.env` in `frontend/`: + ```env + PUBLIC_WS_URL=ws://localhost:8000 + ``` + - Use in Svelte components: + ```javascript + import { PUBLIC_WS_URL } from '$env/static/public'; + const wsUrl = PUBLIC_WS_URL || `ws://${window.location.hostname}:8000`; + ``` + +3. **Backend URL Validation**: + - Update `superset_tool/models.py` (or relevant model file): + ```python + from pydantic import validator + + class ServiceConnection(BaseModel): + base_url: str + + @validator('base_url') + def normalize_url(cls, v): + if not v.endswith('/api/v1'): + return f"{v.rstrip('/')}/api/v1" + return v + ``` + +## Verification Steps + +1. Run backend: `cd backend && uvicorn src.app:app --reload` +2. Run frontend: `cd frontend && npm run dev` +3. Open browser and verify: + - UI is styled (Tailwind classes working). + - Logs appear in real-time (WebSocket connected). + - External service connection accepts base URLs. diff --git a/specs/001-fix-ui-ws-validation/research.md b/specs/001-fix-ui-ws-validation/research.md new file mode 100644 index 0000000..d929180 --- /dev/null +++ b/specs/001-fix-ui-ws-validation/research.md @@ -0,0 +1,41 @@ +# Research: Fix UI Styling, WebSocket Port Mismatch, and URL Validation + +## WebSocket Port Mismatch Resolution + +### Decision +Use SvelteKit's `$env/static/public` for `PUBLIC_WS_URL` with a client-side fallback logic. + +### Rationale +SvelteKit allows exposing environment variables to the frontend. By using a public environment variable, we can explicitly set the WebSocket URL in different environments (dev vs. prod). + +### Alternatives Considered +- **Hardcoding**: Rejected as it breaks across different environments. +- **Relative URLs**: WebSockets (`ws://` or `wss://`) cannot be purely relative in all browser contexts without logic to determine the host and port. + +--- + +## URL Validation Relaxation + +### Decision +Modify the Pydantic model to use a `validator` (or `field_validator` in Pydantic v2) that checks for the `/api/v1` suffix and appends it if missing, while still ensuring the base URL is valid. + +### Rationale +This provides a seamless user experience where they can provide just the base URL, and the system handles the API versioning internally. + +### Alternatives Considered +- **Strict Validation with Error Message**: Rejected as it causes user frustration (as noted in the spec). +- **Manual Suffixing in Service Clients**: Rejected as it's better to have a normalized URL in the data model. + +--- + +## Global Styling (Tailwind CSS) + +### Decision +Import the global CSS file (which includes `@tailwind` directives) in `src/routes/+layout.svelte`. + +### Rationale +This is the standard SvelteKit pattern for ensuring styles are applied globally across all routes. + +### Alternatives Considered +- **Importing in each page**: Rejected as it's redundant and hard to maintain. +- **Importing in `app.html`**: Possible, but importing in `+layout.svelte` allows for better integration with Svelte's build pipeline. diff --git a/specs/001-fix-ui-ws-validation/spec.md b/specs/001-fix-ui-ws-validation/spec.md new file mode 100644 index 0000000..1ac106c --- /dev/null +++ b/specs/001-fix-ui-ws-validation/spec.md @@ -0,0 +1,94 @@ +# Feature Specification: Fix UI Styling, WebSocket Port Mismatch, and URL Validation + +**Feature Branch**: `001-fix-ui-ws-validation` +**Created**: 2025-12-20 +**Status**: Draft +**Input**: User description: "UI Styling: Tailwind CSS is not imported in the root layout, causing the unstyled appearance. WebSocket Mismatch: Port mismatch in dev mode is breaking real-time logs. Validation Error: Strict URL validation in superset_tool/models.py requires /api/v1, which caused the connection failure reported in your feedback." + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 - Consistent UI Styling (Priority: P1) + +As a user, I want the application to have a professional and styled appearance so that I can easily navigate and use the interface. + +**Why this priority**: Unstyled UI makes the application look broken and difficult to use, impacting user trust and usability. + +**Independent Test**: Can be fully tested by opening the application in a browser and verifying that consistent styling is applied globally across all routes. + +**Acceptance Scenarios**: + +1. **Given** the application is running, **When** I navigate to the home page or settings page, **Then** I should see professional styling applied (e.g., correct fonts, colors, and layout). +2. **Given** a new component is added, **When** it uses standard styling classes, **Then** those classes should be rendered correctly without additional imports. + +--- + +### User Story 2 - Real-time Log Monitoring (Priority: P1) + +As a developer or operator, I want to see real-time logs for running tasks so that I can monitor progress and debug issues effectively. + +**Why this priority**: Real-time feedback is essential for long-running tasks like migrations or backups; without it, users are left wondering if the process is stuck. + +**Independent Test**: Can be tested by starting a task and verifying that logs appear in the UI in real-time without requiring a page refresh. + +**Acceptance Scenarios**: + +1. **Given** a task is running, **When** I view the task details page, **Then** I should see live log updates streamed via real-time communication. +2. **Given** the application is running in development mode, **When** a real-time connection is initiated, **Then** it should correctly target the backend service port. + +--- + +### User Story 3 - Flexible External Service Connection (Priority: P2) + +As an administrator, I want to connect to external services using their base URL so that I don't have to worry about specific API version paths during configuration. + +**Why this priority**: Strict validation currently prevents successful connection to valid service instances if the user doesn't provide a very specific suffix, leading to configuration frustration. + +**Independent Test**: Can be tested by configuring a service connection with a standard base URL and verifying it connects successfully. + +**Acceptance Scenarios**: + +1. **Given** a valid service base URL, **When** I save the connection settings, **Then** the system should validate and accept the URL even if it doesn't explicitly end in a specific API version suffix. +2. **Given** a service URL that already includes an API version suffix, **When** I save the settings, **Then** the system should not duplicate the suffix or fail validation. + +--- + +### Edge Cases + +- **Connection Disconnection**: How does the system handle a real-time connection drop during a long-running task? (Assumption: It should attempt to reconnect or show a "Connection Lost" message). +- **Invalid URL Formats**: How does the system handle URLs that are completely malformed? (Assumption: Standard URL validation should still apply). +- **Styling Build Failures**: What happens if the styling assets fail to generate? (Assumption: The app should still be functional but may look unstyled; build logs should indicate the failure). + +## Requirements *(mandatory)* + +### Functional Requirements + +- **FR-001**: System MUST ensure global styling (Tailwind CSS) is imported in `src/routes/+layout.svelte` to ensure consistent appearance. +- **FR-002**: System MUST use an environment variable (e.g., `PUBLIC_WS_URL`) with a fallback to the backend port (8000) to determine the WebSocket connection URL. +- **FR-003**: System MUST relax URL validation for external services to allow base URLs and automatically append `/api/v1` if the version suffix is missing. +- **FR-004**: System MUST provide visual feedback (toast notification and status indicator in log view) when a real-time connection fails to establish. +- **FR-005**: System MUST ensure that service clients correctly handle API versioning internally by using the normalized URL. + +### Key Entities *(include if feature involves data)* + +- **Service Connection**: Represents the configuration for connecting to an external service. + - Attributes: Base URL, Credentials (if applicable), Connection Status. +- **Task Log Stream**: Represents the real-time data flow of logs from the backend to the frontend. + - Attributes: Task ID, Log Message, Timestamp. + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: 100% of pages render with consistent, professional styling as verified by visual inspection. +- **SC-002**: Real-time communication success rate is 100% in the development environment when both frontend and backend are running. +- **SC-003**: Users can successfully configure and save external service connections using only the base domain/IP in 100% of valid cases. +- **SC-004**: Real-time updates appear in the UI within 500ms of being generated on the backend. + +## Clarifications + +### Session 2025-12-20 +- Q: WebSocket Reconnection Strategy → A: Automatic reconnection with exponential backoff (Option A). +- Q: URL Validation Strictness → A: Automatically append `/api/v1` if missing (Option A). +- Q: Global Styling Implementation → A: Import in `src/routes/+layout.svelte` (Option A). +- Q: WebSocket Port Configuration → A: Use environment variable with fallback (Option A). +- Q: Visual Feedback for Connection Failure → A: Toast notification + Status indicator (Option A). diff --git a/specs/001-fix-ui-ws-validation/tasks.md b/specs/001-fix-ui-ws-validation/tasks.md new file mode 100644 index 0000000..466c902 --- /dev/null +++ b/specs/001-fix-ui-ws-validation/tasks.md @@ -0,0 +1,139 @@ +# Tasks: Fix UI Styling, WebSocket Port Mismatch, and URL Validation + +**Input**: Design documents from `/specs/001-fix-ui-ws-validation/` +**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/ + +**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story. + +## Format: `[ID] [P?] [Story] Description` + +- **[P]**: Can run in parallel (different files, no dependencies) +- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3) +- Include exact file paths in descriptions + +## Phase 1: Setup (Shared Infrastructure) + +**Purpose**: Project initialization and basic structure + +- [x] T001 Verify project structure and install dependencies in `backend/` and `frontend/` + +--- + +## Phase 2: Foundational (Blocking Prerequisites) + +**Purpose**: Core infrastructure that MUST be complete before ANY user story can be implemented + +**⚠️ CRITICAL**: No user story work can begin until this phase is complete + +- [x] T002 [P] Configure `PUBLIC_WS_URL` in `frontend/.env` + +**Checkpoint**: Foundation ready - user story implementation can now begin in parallel + +--- + +## Phase 3: User Story 1 - Consistent UI Styling (Priority: P1) 🎯 MVP + +**Goal**: Apply Tailwind CSS globally via the root layout to ensure consistent appearance. + +**Independent Test**: Open the application in a browser and verify that Tailwind styling is applied to all elements (e.g., Navbar, Footer, Buttons). + +### Implementation for User Story 1 + +- [x] T003 [P] [US1] Verify Tailwind directives in `frontend/src/app.css` +- [x] T004 [US1] Import `../app.css` in `frontend/src/routes/+layout.svelte` + +**Checkpoint**: At this point, User Story 1 should be fully functional and testable independently + +--- + +## Phase 4: User Story 2 - Real-time Log Monitoring (Priority: P1) + +**Goal**: Resolve WebSocket port mismatch using environment variables and fallback logic for real-time logs. + +**Independent Test**: Start a task (e.g., a mock migration) and verify that logs appear in the `TaskRunner` component in real-time. + +### Implementation for User Story 2 + +- [x] T005 [P] [US2] Implement WebSocket URL fallback logic in `frontend/src/lib/api.js` +- [x] T006 [US2] Update `frontend/src/components/TaskRunner.svelte` to use the dynamic WebSocket URL + +**Checkpoint**: At this point, User Stories 1 AND 2 should both work independently + +--- + +## Phase 5: User Story 3 - Flexible External Service Connection (Priority: P2) + +**Goal**: Automatically append `/api/v1` to service base URLs if missing to simplify configuration. + +**Independent Test**: Create a new service connection with `http://localhost:8080` and verify it is saved as `http://localhost:8080/api/v1`. + +### Implementation for User Story 3 + +- [x] T007 [P] [US3] Relax `base_url` validation and add normalization in `superset_tool/models.py` +- [x] T008 [US3] Add unit tests for `SupersetConfig` URL normalization in `backend/tests/test_models.py` + +**Checkpoint**: All user stories should now be independently functional + +--- + +## Phase 6: Polish & Cross-Cutting Concerns + +**Purpose**: Improvements that affect multiple user stories + +- [x] T009 [P] Update `docs/settings.md` with new URL validation behavior +- [ ] T010 Run full verification suite per `quickstart.md` + +--- + +## Dependencies & Execution Order + +### Phase Dependencies + +- **Setup (Phase 1)**: No dependencies - can start immediately +- **Foundational (Phase 2)**: Depends on Setup completion - BLOCKS all user stories +- **User Stories (Phase 3+)**: All depend on Foundational phase completion + - User stories can then proceed in parallel (if staffed) + - Or sequentially in priority order (P1 → P2 → P3) +- **Polish (Final Phase)**: Depends on all desired user stories being complete + +### User Story Dependencies + +- **User Story 1 (P1)**: Can start after Foundational (Phase 2) - No dependencies on other stories +- **User Story 2 (P2)**: Can start after Foundational (Phase 2) - May integrate with US1 but should be independently testable +- **User Story 3 (P3)**: Can start after Foundational (Phase 2) - May integrate with US1/US2 but should be independently testable + +### Parallel Opportunities + +- All Setup tasks marked [P] can run in parallel +- All Foundational tasks marked [P] can run in parallel (within Phase 2) +- Once Foundational phase completes, all user stories can start in parallel +- Models within a story marked [P] can run in parallel + +--- + +## Parallel Example: User Story 1 + +```bash +# Launch all models for User Story 1 together: +Task: "Verify Tailwind directives in frontend/src/app.css" +``` + +--- + +## Implementation Strategy + +### MVP First (User Story 1 Only) + +1. Complete Phase 1: Setup +2. Complete Phase 2: Foundational (CRITICAL - blocks all stories) +3. Complete Phase 3: User Story 1 +4. **STOP and VALIDATE**: Test User Story 1 independently +5. Deploy/demo if ready + +### Incremental Delivery + +1. Complete Setup + Foundational → Foundation ready +2. Add User Story 1 → Test independently → Deploy/Demo (MVP!) +3. Add User Story 2 → Test independently → Deploy/Demo +4. Add User Story 3 → Test independently → Deploy/Demo +5. Each story adds value without breaking previous stories diff --git a/specs/004-integrate-svelte-kit/spec.md b/specs/004-integrate-svelte-kit/spec.md index b6b8603..a09f08b 100644 --- a/specs/004-integrate-svelte-kit/spec.md +++ b/specs/004-integrate-svelte-kit/spec.md @@ -66,6 +66,8 @@ As a user, I want a consistent look and feel across all pages with a shared navi - **FR-005**: System MUST handle client-side navigation between routes without full page refreshes. - **FR-006**: System MUST integrate with the existing backend API for data retrieval. - **FR-007**: System MUST support data submission via existing API endpoints using standard asynchronous requests. +- **FR-008**: System MUST support WebSocket proxying for real-time task logs (required by `TaskRunner.svelte`). +- **FR-009**: System MUST support data submission for Settings updates and Plugin actions (e.g., triggering backups). ### Key Entities *(include if feature involves data)* diff --git a/specs/004-integrate-svelte-kit/tasks.md b/specs/004-integrate-svelte-kit/tasks.md index 51172b5..9d24972 100644 --- a/specs/004-integrate-svelte-kit/tasks.md +++ b/specs/004-integrate-svelte-kit/tasks.md @@ -23,9 +23,9 @@ **Purpose**: Project initialization and basic structure -- [ ] T001 Initialize SvelteKit in `frontend/` directory (replacing current setup) -- [ ] T002 Install `@sveltejs/adapter-static` in `frontend/package.json` -- [ ] T003 [P] Configure `frontend/svelte.config.js` for static adapter and SPA fallback +- [x] T001 Initialize SvelteKit in `frontend/` directory (replacing current setup) +- [x] T002 Install `@sveltejs/adapter-static` in `frontend/package.json` +- [x] T003 [P] Configure `frontend/svelte.config.js` for static adapter and SPA fallback --- @@ -35,10 +35,11 @@ **⚠️ CRITICAL**: No user story work can begin until this phase is complete -- [ ] T004 Create `frontend/src/routes/+layout.ts` to disable SSR and prerendering (`ssr = false`, `prerender = false`) -- [ ] T005 Implement catch-all route in `backend/src/app.py` to serve `index.html` for SPA routing -- [ ] T006 [P] Update `backend/src/app.py` to mount `frontend/build` directory using `StaticFiles` -- [ ] T007 [P] Update `frontend/src/lib/api.js` to ensure compatibility with SvelteKit environment +- [x] T004 Create `frontend/src/routes/+layout.ts` to disable SSR and prerendering (`ssr = false`, `prerender = false`) +- [x] T005 Implement catch-all route in `backend/src/app.py` to serve `index.html` for SPA routing +- [x] T006 [P] Update `backend/src/app.py` to mount `frontend/build` directory using `StaticFiles` +- [x] T007 [P] Update `frontend/src/lib/api.js` to ensure compatibility with SvelteKit environment +- [x] T022 [FR-008] Configure WebSocket proxying in `backend/src/app.py` and `frontend/vite.config.js` **Checkpoint**: Foundation ready - user story implementation can now begin in parallel @@ -52,9 +53,11 @@ ### Implementation for User Story 1 -- [ ] T008 [P] [US1] Create Dashboard route in `frontend/src/routes/+page.svelte` (migrating from `App.svelte`/`Dashboard.svelte`) -- [ ] T009 [P] [US1] Create Settings route in `frontend/src/routes/settings/+page.svelte` (migrating from `Settings.svelte`) -- [ ] T010 [US1] Implement navigation links between Dashboard and Settings in `frontend/src/routes/+page.svelte` and `frontend/src/routes/settings/+page.svelte` +- [x] T008 [P] [US1] Create Dashboard route in `frontend/src/routes/+page.svelte` (migrating from `App.svelte`/`Dashboard.svelte`) +- [x] T009 [P] [US1] Create Settings route in `frontend/src/routes/settings/+page.svelte` (migrating from `Settings.svelte`) +- [x] T010 [US1] Implement navigation links between Dashboard and Settings in `frontend/src/routes/+page.svelte` and `frontend/src/routes/settings/+page.svelte` +- [x] T023 [US1] Implement "Save Settings" form submission in `frontend/src/routes/settings/+page.svelte` +- [x] T024 [US1] Implement plugin action triggers (e.g., "Run Backup") in `frontend/src/routes/+page.svelte` **Checkpoint**: At this point, User Story 1 should be fully functional and testable independently. @@ -68,10 +71,10 @@ ### Implementation for User Story 2 -- [ ] T011 [P] [US2] Implement `load` function for Dashboard in `frontend/src/routes/+page.ts` to fetch plugins from `/api/plugins/` -- [ ] T012 [P] [US2] Implement `load` function for Settings in `frontend/src/routes/settings/+page.ts` to fetch config and environments from `/api/settings/` -- [ ] T013 [US2] Update `frontend/src/routes/+page.svelte` to use data from `load` function via `export let data;` -- [ ] T014 [US2] Update `frontend/src/routes/settings/+page.svelte` to use data from `load` function via `export let data;` +- [x] T011 [P] [US2] Implement `load` function for Dashboard in `frontend/src/routes/+page.ts` to fetch plugins from `/api/plugins/` +- [x] T012 [P] [US2] Implement `load` function for Settings in `frontend/src/routes/settings/+page.ts` to fetch config and environments from `/api/settings/` +- [x] T013 [US2] Update `frontend/src/routes/+page.svelte` to use data from `load` function via `export let data;` +- [x] T014 [US2] Update `frontend/src/routes/settings/+page.svelte` to use data from `load` function via `export let data;` **Checkpoint**: At this point, User Stories 1 AND 2 should both work independently. @@ -85,9 +88,9 @@ ### Implementation for User Story 3 -- [ ] T015 [US3] Create shared layout in `frontend/src/routes/+layout.svelte` with `` -- [ ] T016 [P] [US3] Move navigation bar component to `frontend/src/components/Navbar.svelte` and include in `+layout.svelte` -- [ ] T017 [P] [US3] Create footer component in `frontend/src/components/Footer.svelte` and include in `+layout.svelte` +- [x] T015 [US3] Create shared layout in `frontend/src/routes/+layout.svelte` with `` +- [x] T016 [P] [US3] Move navigation bar component to `frontend/src/components/Navbar.svelte` and include in `+layout.svelte` +- [x] T017 [P] [US3] Create footer component in `frontend/src/components/Footer.svelte` and include in `+layout.svelte` **Checkpoint**: All user stories should now be independently functional. @@ -97,10 +100,12 @@ **Purpose**: Improvements that affect multiple user stories -- [ ] T018 [P] Implement custom 404 error page in `frontend/src/routes/+error.svelte` -- [ ] T019 Add graceful error handling for API failures in `load` functions (T011, T012) -- [ ] T020 [P] Update `frontend/README.md` with new SvelteKit-based development and build instructions -- [ ] T021 Run `specs/004-integrate-svelte-kit/quickstart.md` validation +- [x] T018 [P] Implement custom 404 error page in `frontend/src/routes/+error.svelte` +- [x] T019 Add graceful error handling for API failures in `load` functions (T011, T012) +- [x] T020 [P] Update `frontend/README.md` with new SvelteKit-based development and build instructions +- [x] T021 Run `specs/004-integrate-svelte-kit/quickstart.md` validation +- [x] T025 [FR-008] Update `TaskRunner.svelte` to use SvelteKit-compatible WebSocket connection logic +- [x] T026 [SC-001] Perform performance benchmarking to verify < 200ms transition time --- diff --git a/superset_tool/models.py b/superset_tool/models.py index 696361b..c3f108a 100755 --- a/superset_tool/models.py +++ b/superset_tool/models.py @@ -39,19 +39,22 @@ class SupersetConfig(BaseModel): return v # [/DEF:SupersetConfig.validate_auth] - # [DEF:SupersetConfig.check_base_url_format:Function] - # @PURPOSE: Проверяет, что `base_url` соответствует формату URL и содержит `/api/v1`. + # [DEF:SupersetConfig.normalize_base_url:Function] + # @PURPOSE: Нормализует `base_url`, добавляя `/api/v1`, если он отсутствует. # @PRE: `v` должна быть строкой. - # @POST: Возвращает очищенный `v`, если формат корректен. + # @POST: Возвращает нормализованный `v`. # @THROW: ValueError - Если формат URL невалиден. # @PARAM: v (str) - Значение поля base_url. @validator('base_url') - def check_base_url_format(cls, v: str) -> str: + def normalize_base_url(cls, v: str) -> str: v = v.strip() - if not re.fullmatch(r'https?://.+/api/v1/?(?:.*)?', v): - raise ValueError(f"Invalid URL format: {v}. Must include '/api/v1'.") + if not v.startswith(('http://', 'https://')): + raise ValueError(f"Invalid URL scheme: {v}. Must start with http:// or https://") + + if '/api/v1' not in v: + v = f"{v.rstrip('/')}/api/v1" return v - # [/DEF:SupersetConfig.check_base_url_format] + # [/DEF:SupersetConfig.normalize_base_url] class Config: arbitrary_types_allowed = True