aegis-stack 0.2.0rc2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aegis/__init__.py +5 -0
- aegis/__main__.py +51 -0
- aegis/cli/__init__.py +6 -0
- aegis/cli/callbacks.py +114 -0
- aegis/cli/interactive.py +611 -0
- aegis/cli/utils.py +70 -0
- aegis/cli/validators.py +34 -0
- aegis/commands/__init__.py +6 -0
- aegis/commands/add.py +353 -0
- aegis/commands/add_service.py +332 -0
- aegis/commands/components.py +35 -0
- aegis/commands/init.py +370 -0
- aegis/commands/remove.py +227 -0
- aegis/commands/services.py +52 -0
- aegis/commands/update.py +252 -0
- aegis/commands/version.py +12 -0
- aegis/config/__init__.py +1 -0
- aegis/config/shared_files.py +136 -0
- aegis/core/CLAUDE.md +377 -0
- aegis/core/__init__.py +6 -0
- aegis/core/component_files.py +228 -0
- aegis/core/component_utils.py +220 -0
- aegis/core/components.py +127 -0
- aegis/core/copier_manager.py +315 -0
- aegis/core/copier_updater.py +475 -0
- aegis/core/dependency_resolver.py +119 -0
- aegis/core/manual_updater.py +554 -0
- aegis/core/post_gen_tasks.py +547 -0
- aegis/core/service_resolver.py +261 -0
- aegis/core/services.py +157 -0
- aegis/core/template_generator.py +266 -0
- aegis/core/version_compatibility.py +259 -0
- aegis/templates/CLAUDE.md +591 -0
- aegis/templates/cookiecutter-aegis-project/cookiecutter.json +39 -0
- aegis/templates/cookiecutter-aegis-project/hooks/post_gen_project.py +214 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.dockerignore +71 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.env.example.j2 +130 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/.gitignore +131 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/Dockerfile +53 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/Makefile +236 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/README.md.j2 +196 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/alembic.ini.j2 +111 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/env.py.j2 +91 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/script.py.mako +25 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/alembic/versions/001_initial_auth.py.j2 +51 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/__init__.py +5 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/__init__.py +6 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/ai.py.j2 +700 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/ai_rendering.py +361 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/auth.py.j2 +253 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/health.py.j2 +419 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/load_test.py.j2 +656 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/main.py.j2 +65 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/marko_terminal_renderer.py +489 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/tasks.py.j2 +328 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/cli/{% if cookiecutter.include_scheduler == /"yes/" %}tasks.py{% endif %}" +340 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/__init__.py +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/__init__.py +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/ai/__init__.py +8 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/ai/router.py +329 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/auth/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/auth/router.py +64 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/deps.py +58 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/health.py +163 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/models.py.j2 +280 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/routing.py.j2 +32 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/scheduler.py.j2 +121 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/api/worker.py.j2 +478 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/hooks.py +144 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/main.py +31 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/middleware/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/middleware/cors.py +20 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/shutdown/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/shutdown/cleanup.py +14 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/component_health.py.j2 +418 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/backend/startup/database_init.py.j2 +83 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/__init__.py +5 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/__init__.py +27 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/table.py +78 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/controls/text.py +142 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/__init__.py.j2 +47 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/ai_card.py +287 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/auth_card.py +198 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/base_card.py +256 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/card_factory.py +227 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/card_utils.py +333 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/database_card.py +420 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/fastapi_card.py +328 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/flet_card.py +267 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/redis_card.py +322 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/scheduler_card.py +352 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/services_card.py +233 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/dashboard/cards/worker_card.py +684 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/main.py.j2 +653 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/frontend/theme.py +48 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/scheduler/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/scheduler/main.py.j2 +156 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/CLAUDE.md.j2 +213 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/__init__.py +6 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/constants.py.j2 +30 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/pools.py +97 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/load_test.py +55 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/media.py +49 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/queues/system.py +44 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/registry.py +139 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/__init__.py +120 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/load_tasks.py +507 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/simple_system_tasks.py +33 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/components/worker/tasks/system_tasks.py +281 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/config.py.j2 +178 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/constants.py +58 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/db.py.j2 +176 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/log.py +92 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/core/security.py +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/webserver.py +40 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/entrypoints/{% if cookiecutter.include_scheduler == /"yes/" %}scheduler.py{% endif %}" +21 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/integrations/__init__.py +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/integrations/main.py +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/models/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/models/user.py +44 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/py.typed +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/__init__.py +8 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/config.py +130 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/conversation.py +213 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/health.py +96 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/models.py +229 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/providers.py +370 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/ai/service.py +388 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/auth_service.py +41 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/health.py +164 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/auth/user_service.py +83 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/middleware_inspector.py.j2 +223 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/models.py.j2 +70 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/backend/route_inspector.py.j2 +155 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/load_test.py +679 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/load_test_models.py +266 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/__init__.py.j2 +21 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/models.py.j2 +119 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/scheduled_task_manager.py.j2 +273 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/scheduler/task_monitor.py.j2 +189 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/shared/__init__.py +15 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/shared/models.py +26 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/__init__.py +52 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/alerts.py +94 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/backup.py.j2 +119 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/health.py.j2 +1333 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/models.py +243 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/app/services/system/ui.py +52 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto-dark.png +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto-square-backup.png +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/assets/aegis-manifesto.png +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.dockerignore +71 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.env.example.j2 +64 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/.gitignore +131 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/Dockerfile +53 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/Makefile +211 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/README.md.j2 +172 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/docker-compose.yml.j2 +78 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/mkdocs.yml.j2 +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/pyproject.toml.j2 +120 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/clean-validation/uv.lock +1673 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docker-compose.yml.j2 +200 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/api.md +191 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/components/scheduler.md +0 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/components/scheduler.md.j2 +621 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/development.md +215 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/health.md +240 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/javascripts/mermaid-config.js +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/docs/stylesheets/mermaid.css +95 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/mkdocs.yml.j2 +62 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/pyproject.toml.j2 +131 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/entrypoint.sh +87 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/entrypoint.sh.j2 +93 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/scripts/gen_docs.py +16 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_auth_endpoints.py.j2 +307 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_health_endpoints.py.j2 +262 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_scheduler_endpoints.py.j2 +214 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/api/test_worker_endpoints.py.j2 +165 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/cli/test_ai_rendering.py +427 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/cli/test_conversation_memory.py +465 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/components/test_scheduler.py +43 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/conftest.py.j2 +195 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/__init__.py +1 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/conftest.py +78 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_health.py +157 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_models.py +164 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/ai/test_service.py +198 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_auth_integration.py.j2 +528 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_component_integration.py.j2 +387 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_conversation_persistence.py +342 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_health_logic.py.j2 +663 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_load_test_models.py +619 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_load_test_service.py +603 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_middleware_inspector.py.j2 +248 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_scheduled_task_manager.py.j2 +292 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_system_service.py +98 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/services/test_worker_health_registration.py.j2 +257 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/tests/test_core.py +49 -0
- aegis/templates/cookiecutter-aegis-project/{{cookiecutter.project_slug}}/uv.lock +1673 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/.copier-answers.yml.jinja +21 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/.dockerignore +71 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/.env.example.jinja +130 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/.gitignore +131 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/Dockerfile +53 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/Makefile.jinja +236 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/README.md.jinja +196 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/alembic.ini.jinja +111 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/env.py.jinja +91 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/script.py.mako +25 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/alembic/versions/001_initial_auth.py.jinja +51 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/__init__.py.jinja +5 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/__init__.py.jinja +6 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/ai.py.jinja +700 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/ai_rendering.py +360 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/auth.py.jinja +253 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/health.py.jinja +419 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/load_test.py.jinja +656 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/main.py.jinja +65 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/marko_terminal_renderer.py +489 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/cli/tasks.py.jinja +328 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/__init__.py +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/__init__.py +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/ai/__init__.py +8 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/ai/router.py +329 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/auth/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/auth/router.py +64 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/deps.py +58 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/health.py.jinja +163 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/models.py.jinja +280 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/routing.py.jinja +32 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/scheduler.py.jinja +121 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/api/worker.py.jinja +478 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/hooks.py +144 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/main.py +31 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/middleware/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/middleware/cors.py +20 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/shutdown/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/shutdown/cleanup.py +14 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/component_health.py.jinja +418 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/backend/startup/database_init.py.jinja +83 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/__init__.py +5 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/__init__.py +27 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/table.py +78 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/controls/text.py +142 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/__init__.py.jinja +47 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/ai_card.py +287 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/auth_card.py +198 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/base_card.py +256 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/card_factory.py +227 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/card_utils.py +333 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/database_card.py +420 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/fastapi_card.py +328 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/flet_card.py +267 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/redis_card.py +322 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/scheduler_card.py +352 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/services_card.py +233 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/dashboard/cards/worker_card.py +684 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/main.py.jinja +653 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/frontend/theme.py +48 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/scheduler/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/scheduler/main.py.jinja +156 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/CLAUDE.md.jinja +213 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/__init__.py +6 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/constants.py.jinja +30 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/pools.py +97 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/load_test.py +55 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/media.py +49 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/queues/system.py +44 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/registry.py +139 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/__init__.py +120 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/load_tasks.py +507 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/simple_system_tasks.py +33 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/components/worker/tasks/system_tasks.py +281 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/config.py.jinja +178 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/constants.py +58 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/db.py.jinja +176 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/log.py +92 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/core/security.py +62 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/scheduler.py.jinja +21 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/entrypoints/webserver.py +39 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/integrations/__init__.py +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/integrations/main.py +61 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/models/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/models/user.py +44 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/py.typed +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/__init__.py +8 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/config.py +130 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/conversation.py +213 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/health.py +96 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/models.py +229 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/providers.py.jinja +370 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/ai/service.py +387 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/auth_service.py +40 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/health.py +162 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/auth/user_service.py +82 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/middleware_inspector.py.jinja +223 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/models.py.jinja +70 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/backend/route_inspector.py.jinja +155 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/load_test.py +678 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/load_test_models.py +265 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/__init__.py.jinja +21 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/models.py.jinja +119 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/scheduled_task_manager.py.jinja +273 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/scheduler/task_monitor.py.jinja +189 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/shared/__init__.py +15 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/shared/models.py +26 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/__init__.py +52 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/alerts.py +94 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/backup.py.jinja +119 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/health.py.jinja +1333 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/models.py +243 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/app/services/system/ui.py +52 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57223!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57224!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57225!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57533!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57534!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57538!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57897!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57898!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!57904!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58315!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58316!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58324!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58837!aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58838!aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/.!58849!aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto-dark.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto-square-backup.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/assets/aegis-manifesto.png +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/.env.example.jinja +64 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/README.md.jinja +172 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/docker-compose.yml.jinja +78 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/mkdocs.yml.jinja +62 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/clean-validation/pyproject.toml.jinja +120 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docker-compose.yml.jinja +200 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/api.md.jinja +191 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/components/scheduler.md +0 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/components/scheduler.md.jinja +621 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/development.md.jinja +215 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/health.md.jinja +240 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/javascripts/mermaid-config.js +62 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/docs/stylesheets/mermaid.css +95 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/mkdocs.yml.jinja +62 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/pyproject.toml.jinja +131 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/entrypoint.sh +87 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/entrypoint.sh.jinja +93 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/scripts/gen_docs.py +16 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_auth_endpoints.py.jinja +307 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_health_endpoints.py.jinja +262 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_scheduler_endpoints.py.jinja +214 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/api/test_worker_endpoints.py.jinja +165 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/cli/test_ai_rendering.py +427 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/cli/test_conversation_memory.py +465 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/components/test_scheduler.py +43 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/conftest.py.jinja +195 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/__init__.py +1 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/conftest.py +78 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_health.py +157 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_models.py +164 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/ai/test_service.py +198 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_auth_integration.py.jinja +528 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_component_integration.py.jinja +387 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_conversation_persistence.py +342 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_health_logic.py.jinja +663 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_load_test_models.py +619 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_load_test_service.py +603 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_middleware_inspector.py.jinja +248 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_scheduled_task_manager.py.jinja +292 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_system_service.py +98 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/services/test_worker_health_registration.py.jinja +257 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/tests/test_core.py +49 -0
- aegis/templates/copier-aegis-project/{{ project_slug }}/uv.lock +1673 -0
- aegis_stack-0.2.0rc2.dist-info/METADATA +165 -0
- aegis_stack-0.2.0rc2.dist-info/RECORD +392 -0
- aegis_stack-0.2.0rc2.dist-info/WHEEL +4 -0
- aegis_stack-0.2.0rc2.dist-info/entry_points.txt +3 -0
- aegis_stack-0.2.0rc2.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Component health registration startup hook.
|
|
3
|
+
|
|
4
|
+
Automatically detects available components and registers their health checks
|
|
5
|
+
with the system health service using Python's import system.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from app.core.log import logger
|
|
9
|
+
from app.services.system.health import register_health_check
|
|
10
|
+
from app.services.system.models import ComponentStatus, ComponentStatusType
|
|
11
|
+
from app.components.backend.main import get_configured_app
|
|
12
|
+
from app.services.backend.route_inspector import get_fastapi_route_metadata, RouteMetadata
|
|
13
|
+
from app.services.backend.middleware_inspector import get_fastapi_middleware_metadata, MiddlewareMetadata
|
|
14
|
+
|
|
15
|
+
# Cache for route metadata - initialized once at startup
|
|
16
|
+
_cached_route_metadata: RouteMetadata | None = None
|
|
17
|
+
# Cache for middleware metadata - initialized once at startup
|
|
18
|
+
_cached_middleware_metadata: MiddlewareMetadata | None = None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _initialize_route_metadata_cache() -> None:
|
|
22
|
+
"""
|
|
23
|
+
Initialize route and middleware metadata caches using the configured FastAPI app.
|
|
24
|
+
Called once during startup to avoid recreating the app on every health check.
|
|
25
|
+
"""
|
|
26
|
+
global _cached_route_metadata, _cached_middleware_metadata
|
|
27
|
+
|
|
28
|
+
if _cached_route_metadata is not None and _cached_middleware_metadata is not None:
|
|
29
|
+
return # Already initialized
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
app = get_configured_app()
|
|
33
|
+
if app is not None:
|
|
34
|
+
# Cache route metadata
|
|
35
|
+
if _cached_route_metadata is None:
|
|
36
|
+
_cached_route_metadata = get_fastapi_route_metadata(app)
|
|
37
|
+
logger.info(
|
|
38
|
+
f"Route metadata cached: "
|
|
39
|
+
f"{_cached_route_metadata.total_routes} routes, "
|
|
40
|
+
f"{_cached_route_metadata.total_endpoints} endpoints"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# Cache middleware metadata
|
|
44
|
+
if _cached_middleware_metadata is None:
|
|
45
|
+
_cached_middleware_metadata = get_fastapi_middleware_metadata(app)
|
|
46
|
+
logger.info(
|
|
47
|
+
f"Middleware metadata cached: "
|
|
48
|
+
f"{_cached_middleware_metadata.total_middleware} middleware, "
|
|
49
|
+
f"{_cached_middleware_metadata.security_count} security layers"
|
|
50
|
+
)
|
|
51
|
+
else:
|
|
52
|
+
logger.warning(
|
|
53
|
+
"FastAPI app not yet configured - route and middleware metadata "
|
|
54
|
+
"cache will be initialized later"
|
|
55
|
+
)
|
|
56
|
+
except Exception as e:
|
|
57
|
+
logger.error(f"Failed to initialize route and middleware metadata cache: {e}")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
async def _backend_component_health() -> ComponentStatus:
|
|
61
|
+
"""
|
|
62
|
+
FastAPI backend health check with route and middleware introspection.
|
|
63
|
+
|
|
64
|
+
In test environment, reports as healthy since the app is loaded.
|
|
65
|
+
In production, uses internal check to avoid circular dependency.
|
|
66
|
+
Includes comprehensive route and middleware metadata for dashboard display.
|
|
67
|
+
"""
|
|
68
|
+
import os
|
|
69
|
+
global _cached_route_metadata, _cached_middleware_metadata
|
|
70
|
+
|
|
71
|
+
# Check if we're in test environment
|
|
72
|
+
if os.getenv("PYTEST_CURRENT_TEST") or "pytest" in os.getenv("_", ""):
|
|
73
|
+
# Even in test mode, try to get route and middleware information if possible
|
|
74
|
+
try:
|
|
75
|
+
|
|
76
|
+
# Initialize cache if not already done (might happen in tests)
|
|
77
|
+
if _cached_route_metadata is None or _cached_middleware_metadata is None:
|
|
78
|
+
_initialize_route_metadata_cache()
|
|
79
|
+
|
|
80
|
+
route_metadata = _cached_route_metadata
|
|
81
|
+
middleware_metadata = _cached_middleware_metadata
|
|
82
|
+
|
|
83
|
+
# Handle case where metadata is not available in test mode
|
|
84
|
+
if route_metadata is None or middleware_metadata is None:
|
|
85
|
+
return ComponentStatus(
|
|
86
|
+
name="backend",
|
|
87
|
+
status=ComponentStatusType.HEALTHY,
|
|
88
|
+
message="FastAPI backend available (test mode)",
|
|
89
|
+
response_time_ms=None,
|
|
90
|
+
metadata={
|
|
91
|
+
"type": "component_check",
|
|
92
|
+
"environment": "test",
|
|
93
|
+
"note": "Backend component loaded successfully",
|
|
94
|
+
"route_introspection": "unavailable",
|
|
95
|
+
"middleware_introspection": "unavailable",
|
|
96
|
+
},
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Create message with both route and middleware info
|
|
100
|
+
message_parts = [f"{route_metadata.total_routes} routes"]
|
|
101
|
+
if middleware_metadata.security_count > 0:
|
|
102
|
+
message_parts.append(
|
|
103
|
+
f"{middleware_metadata.security_count} security layers"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
return ComponentStatus(
|
|
107
|
+
name="backend",
|
|
108
|
+
status=ComponentStatusType.HEALTHY,
|
|
109
|
+
message=(
|
|
110
|
+
f"FastAPI backend available (test mode): "
|
|
111
|
+
f"{', '.join(message_parts)}"
|
|
112
|
+
),
|
|
113
|
+
response_time_ms=None,
|
|
114
|
+
metadata={
|
|
115
|
+
"type": "component_check",
|
|
116
|
+
"environment": "test",
|
|
117
|
+
"note": "Backend component loaded successfully",
|
|
118
|
+
**route_metadata.model_dump_for_metadata(),
|
|
119
|
+
**middleware_metadata.model_dump_for_metadata(),
|
|
120
|
+
},
|
|
121
|
+
)
|
|
122
|
+
except Exception as e:
|
|
123
|
+
logger.warning(
|
|
124
|
+
f"Could not get route and middleware metadata in test mode: {e}"
|
|
125
|
+
)
|
|
126
|
+
return ComponentStatus(
|
|
127
|
+
name="backend",
|
|
128
|
+
status=ComponentStatusType.HEALTHY,
|
|
129
|
+
message="FastAPI backend available (test mode)",
|
|
130
|
+
response_time_ms=None,
|
|
131
|
+
metadata={
|
|
132
|
+
"type": "component_check",
|
|
133
|
+
"environment": "test",
|
|
134
|
+
"note": "Backend component loaded successfully",
|
|
135
|
+
"route_introspection_error": str(e),
|
|
136
|
+
"middleware_introspection_error": str(e),
|
|
137
|
+
},
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# In production, use cached route and middleware information
|
|
141
|
+
try:
|
|
142
|
+
# Initialize cache if not already done (fallback safety)
|
|
143
|
+
if _cached_route_metadata is None or _cached_middleware_metadata is None:
|
|
144
|
+
logger.warning(
|
|
145
|
+
"Route and middleware metadata cache not initialized at startup, "
|
|
146
|
+
"initializing now..."
|
|
147
|
+
)
|
|
148
|
+
_initialize_route_metadata_cache()
|
|
149
|
+
|
|
150
|
+
route_metadata = _cached_route_metadata
|
|
151
|
+
middleware_metadata = _cached_middleware_metadata
|
|
152
|
+
|
|
153
|
+
# Handle case where metadata is still not available
|
|
154
|
+
if route_metadata is None or middleware_metadata is None:
|
|
155
|
+
return ComponentStatus(
|
|
156
|
+
name="backend",
|
|
157
|
+
status=ComponentStatusType.HEALTHY,
|
|
158
|
+
message=(
|
|
159
|
+
"FastAPI backend active (introspection unavailable)"
|
|
160
|
+
),
|
|
161
|
+
response_time_ms=None,
|
|
162
|
+
metadata={
|
|
163
|
+
"type": "internal_component_check",
|
|
164
|
+
"note": (
|
|
165
|
+
"Backend is running but route/middleware metadata unavailable"
|
|
166
|
+
),
|
|
167
|
+
"check_method": "internal_execution",
|
|
168
|
+
},
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# Create descriptive message based on route and middleware data
|
|
172
|
+
total_routes = route_metadata.total_routes
|
|
173
|
+
total_endpoints = route_metadata.total_endpoints
|
|
174
|
+
method_counts = route_metadata.method_counts
|
|
175
|
+
security_count = middleware_metadata.security_count
|
|
176
|
+
|
|
177
|
+
# Format method summary (e.g., "12 GET, 5 POST")
|
|
178
|
+
method_summary = ", ".join([
|
|
179
|
+
f"{count} {method}"
|
|
180
|
+
for method, count in sorted(method_counts.items())
|
|
181
|
+
])
|
|
182
|
+
|
|
183
|
+
message_parts = [f"{total_routes} routes"]
|
|
184
|
+
if total_endpoints != total_routes:
|
|
185
|
+
message_parts.append(f"{total_endpoints} endpoints")
|
|
186
|
+
if security_count > 0:
|
|
187
|
+
message_parts.append(f"{security_count} security layers")
|
|
188
|
+
if method_summary:
|
|
189
|
+
message_parts.append(f"({method_summary})")
|
|
190
|
+
|
|
191
|
+
message = f"FastAPI backend active: {', '.join(message_parts)}"
|
|
192
|
+
|
|
193
|
+
return ComponentStatus(
|
|
194
|
+
name="backend",
|
|
195
|
+
status=ComponentStatusType.HEALTHY,
|
|
196
|
+
message=message,
|
|
197
|
+
response_time_ms=None,
|
|
198
|
+
metadata={
|
|
199
|
+
"type": "internal_component_check",
|
|
200
|
+
"note": (
|
|
201
|
+
"Backend is running since this health check executed"
|
|
202
|
+
),
|
|
203
|
+
"check_method": "internal_execution",
|
|
204
|
+
**route_metadata.model_dump_for_metadata(),
|
|
205
|
+
**middleware_metadata.model_dump_for_metadata(),
|
|
206
|
+
},
|
|
207
|
+
)
|
|
208
|
+
except Exception as e:
|
|
209
|
+
return ComponentStatus(
|
|
210
|
+
name="backend",
|
|
211
|
+
status=ComponentStatusType.UNHEALTHY,
|
|
212
|
+
message=f"Backend component check failed: {str(e)}",
|
|
213
|
+
response_time_ms=None,
|
|
214
|
+
metadata={
|
|
215
|
+
"type": "internal_component_check",
|
|
216
|
+
"error": "import_or_execution_error",
|
|
217
|
+
"error_details": str(e),
|
|
218
|
+
},
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
async def _frontend_component_health() -> ComponentStatus:
|
|
223
|
+
"""
|
|
224
|
+
Flet frontend health check.
|
|
225
|
+
|
|
226
|
+
Since the frontend runs in the same process as the backend,
|
|
227
|
+
we check if the frontend component is properly initialized.
|
|
228
|
+
"""
|
|
229
|
+
try:
|
|
230
|
+
# Check if frontend component is available
|
|
231
|
+
from app.components.frontend.main import create_frontend_app
|
|
232
|
+
|
|
233
|
+
# Verify the frontend app factory function works
|
|
234
|
+
create_frontend_app()
|
|
235
|
+
|
|
236
|
+
return ComponentStatus(
|
|
237
|
+
name="frontend",
|
|
238
|
+
status=ComponentStatusType.HEALTHY,
|
|
239
|
+
message="Flet frontend component available",
|
|
240
|
+
response_time_ms=None,
|
|
241
|
+
metadata={
|
|
242
|
+
"type": "component_check",
|
|
243
|
+
"framework": "flet",
|
|
244
|
+
"note": "Frontend integrated with FastAPI",
|
|
245
|
+
},
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
except ImportError as e:
|
|
249
|
+
return ComponentStatus(
|
|
250
|
+
name="frontend",
|
|
251
|
+
status=ComponentStatusType.UNHEALTHY,
|
|
252
|
+
message="Frontend component not found",
|
|
253
|
+
response_time_ms=None,
|
|
254
|
+
metadata={
|
|
255
|
+
"type": "component_check",
|
|
256
|
+
"error": "import_error",
|
|
257
|
+
"error_details": str(e),
|
|
258
|
+
},
|
|
259
|
+
)
|
|
260
|
+
except Exception as e:
|
|
261
|
+
return ComponentStatus(
|
|
262
|
+
name="frontend",
|
|
263
|
+
status=ComponentStatusType.UNHEALTHY,
|
|
264
|
+
message=f"Frontend component error: {str(e)}",
|
|
265
|
+
response_time_ms=None,
|
|
266
|
+
metadata={
|
|
267
|
+
"type": "component_check",
|
|
268
|
+
"error": "unexpected_error",
|
|
269
|
+
"error_details": str(e),
|
|
270
|
+
},
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
{%- if cookiecutter.include_scheduler == "yes" %}
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
async def _scheduler_component_health() -> ComponentStatus:
|
|
277
|
+
"""
|
|
278
|
+
Check scheduler component health from backend.
|
|
279
|
+
{%- if cookiecutter.scheduler_backend != "memory" %}
|
|
280
|
+
|
|
281
|
+
With persistence: Gets real task data from database
|
|
282
|
+
{%- else %}
|
|
283
|
+
|
|
284
|
+
Without persistence: Shows component as activated only
|
|
285
|
+
{%- endif %}
|
|
286
|
+
"""
|
|
287
|
+
{% if cookiecutter.scheduler_backend != "memory" %}
|
|
288
|
+
try:
|
|
289
|
+
from app.services.scheduler.task_monitor import TaskHealthMonitor
|
|
290
|
+
monitor = TaskHealthMonitor()
|
|
291
|
+
# No scheduler instance available in backend
|
|
292
|
+
health_data = await monitor.get_health_metadata(None)
|
|
293
|
+
|
|
294
|
+
# Format message based on task data
|
|
295
|
+
total_tasks = health_data.total_tasks
|
|
296
|
+
if total_tasks > 0:
|
|
297
|
+
message = f"Scheduler running with {total_tasks} tasks"
|
|
298
|
+
else:
|
|
299
|
+
message = "Scheduler running (no tasks)"
|
|
300
|
+
|
|
301
|
+
return ComponentStatus(
|
|
302
|
+
name="scheduler",
|
|
303
|
+
status=ComponentStatusType.HEALTHY,
|
|
304
|
+
message=message,
|
|
305
|
+
response_time_ms=None,
|
|
306
|
+
metadata=health_data.model_dump(),
|
|
307
|
+
)
|
|
308
|
+
except Exception as e:
|
|
309
|
+
logger.error("Failed to get scheduler health data", error=str(e))
|
|
310
|
+
# Fallback to basic status
|
|
311
|
+
return ComponentStatus(
|
|
312
|
+
name="scheduler",
|
|
313
|
+
status=ComponentStatusType.WARNING,
|
|
314
|
+
message="Scheduler enabled, health data unavailable",
|
|
315
|
+
response_time_ms=None,
|
|
316
|
+
metadata={
|
|
317
|
+
"type": "component_status",
|
|
318
|
+
"error": "health_check_failed",
|
|
319
|
+
"error_details": str(e),
|
|
320
|
+
},
|
|
321
|
+
)
|
|
322
|
+
{% else %}
|
|
323
|
+
return ComponentStatus(
|
|
324
|
+
name="scheduler",
|
|
325
|
+
status=ComponentStatusType.HEALTHY,
|
|
326
|
+
message="Scheduler component activated",
|
|
327
|
+
response_time_ms=None,
|
|
328
|
+
metadata={
|
|
329
|
+
"type": "component_status",
|
|
330
|
+
"deployment": "separate_container",
|
|
331
|
+
"status": "activated",
|
|
332
|
+
"note": "Memory-only mode - no cross-container health monitoring",
|
|
333
|
+
},
|
|
334
|
+
)
|
|
335
|
+
{% endif %}
|
|
336
|
+
{%- endif %}
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
async def startup_hook() -> None:
|
|
340
|
+
"""
|
|
341
|
+
Auto-detect available components and register their health checks.
|
|
342
|
+
|
|
343
|
+
Always registers core components (backend, frontend) and detects
|
|
344
|
+
optional components using Python's import system.
|
|
345
|
+
"""
|
|
346
|
+
logger.info("Registering component health checks...")
|
|
347
|
+
|
|
348
|
+
# Initialize route metadata cache once at startup
|
|
349
|
+
_initialize_route_metadata_cache()
|
|
350
|
+
|
|
351
|
+
# Always register core components
|
|
352
|
+
register_health_check("backend", _backend_component_health)
|
|
353
|
+
logger.info("Backend component health check registered")
|
|
354
|
+
|
|
355
|
+
register_health_check("frontend", _frontend_component_health)
|
|
356
|
+
logger.info("️Frontend component health check registered")
|
|
357
|
+
|
|
358
|
+
{%- if cookiecutter.include_scheduler == "yes" %}
|
|
359
|
+
# Register scheduler component health check
|
|
360
|
+
register_health_check("scheduler", _scheduler_component_health)
|
|
361
|
+
{% if cookiecutter.scheduler_backend != "memory" %}
|
|
362
|
+
logger.info("Scheduler component health check registered (with task data)")
|
|
363
|
+
{% else %}
|
|
364
|
+
logger.info("Scheduler component enabled (shows as activated)")
|
|
365
|
+
{% endif %}
|
|
366
|
+
{%- endif %}
|
|
367
|
+
|
|
368
|
+
{%- if cookiecutter.include_worker == "yes" %}
|
|
369
|
+
# Register worker health check (shows queue status and job metrics)
|
|
370
|
+
from app.services.system.health import check_worker_health
|
|
371
|
+
register_health_check("worker", check_worker_health)
|
|
372
|
+
logger.info("Worker component health check registered")
|
|
373
|
+
{%- endif %}
|
|
374
|
+
|
|
375
|
+
{%- if cookiecutter.include_redis == "yes" %}
|
|
376
|
+
# Register cache health check (Redis connectivity and operations)
|
|
377
|
+
from app.services.system.health import check_cache_health
|
|
378
|
+
register_health_check("cache", check_cache_health)
|
|
379
|
+
logger.info("Cache component health check registered")
|
|
380
|
+
{%- endif %}
|
|
381
|
+
|
|
382
|
+
{%- if cookiecutter.include_database == "yes" %}
|
|
383
|
+
# Register database health check (SQLite connectivity and basic operations)
|
|
384
|
+
from app.services.system.health import check_database_health
|
|
385
|
+
register_health_check("database", check_database_health)
|
|
386
|
+
logger.info("Database component health check registered")
|
|
387
|
+
{%- endif %}
|
|
388
|
+
|
|
389
|
+
logger.info("✅ Component health detection complete")
|
|
390
|
+
|
|
391
|
+
# ==========================================
|
|
392
|
+
# Service Health Checks Registration
|
|
393
|
+
# ==========================================
|
|
394
|
+
|
|
395
|
+
from app.services.system.health import register_service_health_check
|
|
396
|
+
|
|
397
|
+
logger.info("🔧 Registering service health checks...")
|
|
398
|
+
|
|
399
|
+
{%- if cookiecutter.include_auth == "yes" %}
|
|
400
|
+
# Register auth service health check
|
|
401
|
+
from app.services.auth.health import check_auth_service_health
|
|
402
|
+
register_service_health_check("auth", check_auth_service_health)
|
|
403
|
+
logger.info("Auth service health check registered")
|
|
404
|
+
{%- endif %}
|
|
405
|
+
|
|
406
|
+
{%- if cookiecutter.include_ai == "yes" %}
|
|
407
|
+
# Register AI service health check
|
|
408
|
+
from app.services.ai.health import check_ai_service_health
|
|
409
|
+
register_service_health_check("ai", check_ai_service_health)
|
|
410
|
+
logger.info("AI service health check registered")
|
|
411
|
+
{%- endif %}
|
|
412
|
+
|
|
413
|
+
# Future services will be registered here:
|
|
414
|
+
# Example:
|
|
415
|
+
# from app.services.payment.health import check_payment_service_health
|
|
416
|
+
# register_service_health_check("payment", check_payment_service_health)
|
|
417
|
+
|
|
418
|
+
logger.info("✅ Service health detection complete")
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Database initialization startup hook.
|
|
3
|
+
|
|
4
|
+
Ensures database directory structure exists and verifies connectivity
|
|
5
|
+
when the backend starts up (only when database component is included).
|
|
6
|
+
"""
|
|
7
|
+
{% if cookiecutter.include_database == "yes" %}
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from app.core.db import init_database
|
|
11
|
+
from app.core.log import logger
|
|
12
|
+
|
|
13
|
+
{% if cookiecutter.include_auth == "yes" %}
|
|
14
|
+
# Import models to register them with SQLModel metadata
|
|
15
|
+
from app.models.user import User # noqa: F401
|
|
16
|
+
{% endif %}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
async def startup_database_init() -> None:
|
|
20
|
+
"""
|
|
21
|
+
Initialize database directory structure and verify connectivity.
|
|
22
|
+
|
|
23
|
+
This hook runs when the backend starts to ensure the database
|
|
24
|
+
directory exists and connection works. For auth service projects,
|
|
25
|
+
migrations should already be applied during project generation.
|
|
26
|
+
"""
|
|
27
|
+
try:
|
|
28
|
+
# Ensure database directory exists
|
|
29
|
+
from app.core.db import DATABASE_PATH
|
|
30
|
+
db_path = Path(DATABASE_PATH)
|
|
31
|
+
db_path.parent.mkdir(parents=True, exist_ok=True)
|
|
32
|
+
|
|
33
|
+
{% if cookiecutter.include_auth == "yes" %}
|
|
34
|
+
# Auth service - verify database and migration status
|
|
35
|
+
try:
|
|
36
|
+
from app.core.db import db_session
|
|
37
|
+
from sqlmodel import select, func, text
|
|
38
|
+
from sqlalchemy import inspect
|
|
39
|
+
|
|
40
|
+
with db_session(autocommit=False) as session:
|
|
41
|
+
# Check 1: Basic database connectivity
|
|
42
|
+
session.exec(text("SELECT 1"))
|
|
43
|
+
|
|
44
|
+
# Check 2: Auth tables exist (User table specifically)
|
|
45
|
+
session.exec(select(func.count()).select_from(User))
|
|
46
|
+
|
|
47
|
+
# Check 3: Alembic migration system is set up
|
|
48
|
+
inspector = inspect(session.connection())
|
|
49
|
+
table_names = inspector.get_table_names()
|
|
50
|
+
|
|
51
|
+
if "alembic_version" in table_names:
|
|
52
|
+
logger.info(
|
|
53
|
+
"✅ Database connectivity and auth schema verified "
|
|
54
|
+
"(migrations applied)"
|
|
55
|
+
)
|
|
56
|
+
else:
|
|
57
|
+
logger.warning(
|
|
58
|
+
"⚠️ alembic_version table missing - migrations may not be "
|
|
59
|
+
"fully applied"
|
|
60
|
+
)
|
|
61
|
+
logger.warning(
|
|
62
|
+
"💡 Run 'alembic upgrade head' to ensure all migrations "
|
|
63
|
+
"are applied"
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
except Exception as e:
|
|
67
|
+
logger.warning(f"⚠️ Database check failed: {e}")
|
|
68
|
+
logger.warning("💡 Run 'alembic upgrade head' to apply migrations")
|
|
69
|
+
# Don't fail startup - let the app run and show clear errors
|
|
70
|
+
{% else %}
|
|
71
|
+
# Database component only - ensure tables exist
|
|
72
|
+
init_database()
|
|
73
|
+
logger.info("🗃️ Database initialization completed")
|
|
74
|
+
{% endif %}
|
|
75
|
+
|
|
76
|
+
except Exception as e:
|
|
77
|
+
logger.error(f"❌ Database initialization failed: {e}")
|
|
78
|
+
raise
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# Export the startup hook function
|
|
82
|
+
startup_hook = startup_database_init
|
|
83
|
+
{% endif %}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Frontend UI controls for styled components."""
|
|
2
|
+
|
|
3
|
+
from .table import (
|
|
4
|
+
TableCellText,
|
|
5
|
+
TableHeaderText,
|
|
6
|
+
TableNameText,
|
|
7
|
+
)
|
|
8
|
+
from .text import (
|
|
9
|
+
ConfirmationText,
|
|
10
|
+
LabelText,
|
|
11
|
+
MetricText,
|
|
12
|
+
PrimaryText,
|
|
13
|
+
SecondaryText,
|
|
14
|
+
TitleText,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"PrimaryText",
|
|
19
|
+
"SecondaryText",
|
|
20
|
+
"TitleText",
|
|
21
|
+
"ConfirmationText",
|
|
22
|
+
"MetricText",
|
|
23
|
+
"LabelText",
|
|
24
|
+
"TableHeaderText",
|
|
25
|
+
"TableCellText",
|
|
26
|
+
"TableNameText",
|
|
27
|
+
]
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Table-specific text controls for consistent styling across cards.
|
|
3
|
+
|
|
4
|
+
These controls provide standardized text styling for table headers, cells, and
|
|
5
|
+
entity names to ensure consistency between worker, database, and other component cards.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
import flet as ft
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TableHeaderText(ft.Text): # type: ignore[misc]
|
|
14
|
+
"""
|
|
15
|
+
Table header text control with consistent styling.
|
|
16
|
+
|
|
17
|
+
Used for column headers in component cards. Provides medium weight text
|
|
18
|
+
with reduced opacity for visual hierarchy.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, text: str, **kwargs: Any) -> None:
|
|
22
|
+
# Set defaults that can be overridden
|
|
23
|
+
defaults = {
|
|
24
|
+
"weight": ft.FontWeight.W_500,
|
|
25
|
+
"size": 12,
|
|
26
|
+
"color": ft.Colors.GREY_600,
|
|
27
|
+
}
|
|
28
|
+
defaults.update(kwargs)
|
|
29
|
+
|
|
30
|
+
super().__init__(
|
|
31
|
+
text,
|
|
32
|
+
**defaults,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class TableCellText(ft.Text): # type: ignore[misc]
|
|
37
|
+
"""
|
|
38
|
+
Table cell text control for data values.
|
|
39
|
+
|
|
40
|
+
Used for displaying data values in table cells. Provides consistent
|
|
41
|
+
sizing and coloring for tabular data.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(self, text: str, **kwargs: Any) -> None:
|
|
45
|
+
# Set defaults that can be overridden
|
|
46
|
+
defaults = {
|
|
47
|
+
"size": 11,
|
|
48
|
+
"color": ft.Colors.ON_SURFACE,
|
|
49
|
+
}
|
|
50
|
+
defaults.update(kwargs)
|
|
51
|
+
|
|
52
|
+
super().__init__(
|
|
53
|
+
text,
|
|
54
|
+
**defaults,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class TableNameText(ft.Text): # type: ignore[misc]
|
|
59
|
+
"""
|
|
60
|
+
Table entity name text control.
|
|
61
|
+
|
|
62
|
+
Used for displaying entity names (queues, tables, etc.) in table rows.
|
|
63
|
+
Provides consistent styling for entity identifiers.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __init__(self, text: str, **kwargs: Any) -> None:
|
|
67
|
+
# Set defaults that can be overridden
|
|
68
|
+
defaults = {
|
|
69
|
+
"weight": ft.FontWeight.W_400,
|
|
70
|
+
"size": 11,
|
|
71
|
+
"color": ft.Colors.ON_SURFACE,
|
|
72
|
+
}
|
|
73
|
+
defaults.update(kwargs)
|
|
74
|
+
|
|
75
|
+
super().__init__(
|
|
76
|
+
text,
|
|
77
|
+
**defaults,
|
|
78
|
+
)
|