from __future__ import annotations import sqlite3 from pathlib import Path from app.config import settings SCHEMA = """ PRAGMA journal_mode = WAL; PRAGMA foreign_keys = ON; CREATE TABLE IF NOT EXISTS tasks ( id TEXT PRIMARY KEY, type TEXT NOT NULL, app_id TEXT, app_name TEXT, status TEXT NOT NULL, progress INTEGER DEFAULT 0, current_step TEXT, current_component_id TEXT, error_message TEXT, created_at TEXT NOT NULL, started_at TEXT, finished_at TEXT ); CREATE TABLE IF NOT EXISTS task_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, task_id TEXT NOT NULL, timestamp TEXT NOT NULL, level TEXT NOT NULL, message TEXT NOT NULL, FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS installed_apps ( app_id TEXT PRIMARY KEY, app_name TEXT NOT NULL, version TEXT NOT NULL, manifest_hash TEXT, status TEXT NOT NULL, installed_at TEXT NOT NULL, updated_at TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS installed_components ( id INTEGER PRIMARY KEY AUTOINCREMENT, app_id TEXT NOT NULL, component_id TEXT NOT NULL, type TEXT NOT NULL, install_order INTEGER NOT NULL, status TEXT NOT NULL, package_name TEXT, package_version TEXT, service_name TEXT, docker_image TEXT, docker_digest TEXT, container_name TEXT, compose_project_name TEXT, installed_at TEXT NOT NULL, updated_at TEXT NOT NULL, UNIQUE(app_id, component_id) ); CREATE TABLE IF NOT EXISTS task_components ( id INTEGER PRIMARY KEY AUTOINCREMENT, task_id TEXT NOT NULL, app_id TEXT NOT NULL, component_id TEXT NOT NULL, type TEXT NOT NULL, install_order INTEGER NOT NULL, status TEXT NOT NULL, progress INTEGER DEFAULT 0, current_step TEXT, error_message TEXT, started_at TEXT, finished_at TEXT, FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS agent_config ( key TEXT PRIMARY KEY, value TEXT NOT NULL ); """ def get_connection() -> sqlite3.Connection: connection = sqlite3.connect(settings.db_path, timeout=30) connection.row_factory = sqlite3.Row return connection def initialize_database() -> None: db_path = Path(settings.db_path) db_path.parent.mkdir(parents=True, exist_ok=True) settings.cache_dir.mkdir(parents=True, exist_ok=True) settings.log_dir.mkdir(parents=True, exist_ok=True) with get_connection() as connection: connection.executescript(SCHEMA)