from __future__ import annotations import json import sqlite3 from datetime import datetime, timezone from typing import Any class MethodsRepository: def __init__(self, conn: sqlite3.Connection) -> None: self._conn = conn @staticmethod def _now() -> str: return datetime.now(timezone.utc).isoformat(timespec="milliseconds").replace( "+00:00", "Z", ) def create_method( self, method_id: str, name: str, description: str | None = None, ) -> None: self._conn.execute( """ INSERT INTO crack_methods ( id, name, description, created_at ) VALUES (?, ?, ?, ?) """, ( method_id, name, description, self._now(), ), ) def get_method(self, method_id: str) -> sqlite3.Row | None: row = self._conn.execute( """ SELECT id, name, description, created_at FROM crack_methods WHERE id = ? """, (method_id,), ).fetchone() return row def list_methods(self) -> list[sqlite3.Row]: return self._conn.execute( """ SELECT id, name, description, created_at FROM crack_methods ORDER BY id """ ).fetchall() def create_method_version( self, method_id: str, version: int, definition: dict[str, Any], ) -> None: self._conn.execute( """ INSERT INTO crack_method_versions ( method_id, version, definition_json, created_at ) VALUES (?, ?, ?, ?) """, ( method_id, version, json.dumps( definition, ensure_ascii=False, separators=(",", ":"), sort_keys=True, ), self._now(), ), ) def get_method_version( self, method_id: str, version: int, ) -> sqlite3.Row | None: return self._conn.execute( """ SELECT method_id, version, definition_json, created_at FROM crack_method_versions WHERE method_id = ? AND version = ? """, (method_id, version), ).fetchone() def list_method_versions( self, method_id: str, ) -> list[sqlite3.Row]: return self._conn.execute( """ SELECT method_id, version, definition_json, created_at FROM crack_method_versions WHERE method_id = ? ORDER BY version """, (method_id,), ).fetchall() def get_next_method_version(self, method_id: str) -> int: row = self._conn.execute( """ SELECT COALESCE(MAX(version), 0) + 1 FROM crack_method_versions WHERE method_id = ? """, (method_id,), ).fetchone() return int(row[0])