""" Repository interfaces for Information Spaces. This module defines abstract base classes for space data access, following the repository pattern for clean separation of concerns. """ from abc import ABC, abstractmethod from typing import List, Optional, Dict, Any from ..models import ( InformationSpace, SpaceDocument, SpaceVariable, TransclusionReference, ) class ISpaceRepository(ABC): """ Abstract repository interface for InformationSpace persistence. Implementations should handle CRUD operations for spaces, including proper transaction management and error handling. """ @abstractmethod def create(self, space: InformationSpace) -> InformationSpace: """ Create a new space in the repository. Args: space: The space to create Returns: The created space with any generated fields populated Raises: ValueError: If space with same name already exists """ pass @abstractmethod def get_by_id(self, space_id: str) -> Optional[InformationSpace]: """ Retrieve a space by its ID. Args: space_id: The unique space identifier Returns: The space if found, None otherwise """ pass @abstractmethod def get_by_name(self, name: str) -> Optional[InformationSpace]: """ Retrieve a space by its unique name. Args: name: The space name Returns: The space if found, None otherwise """ pass @abstractmethod def list_all(self, include_archived: bool = False) -> List[InformationSpace]: """ List all spaces in the repository. Args: include_archived: Whether to include archived spaces Returns: List of all spaces """ pass @abstractmethod def update(self, space: InformationSpace) -> InformationSpace: """ Update an existing space. Args: space: The space with updated values Returns: The updated space Raises: ValueError: If space does not exist """ pass @abstractmethod def delete(self, space_id: str) -> bool: """ Delete a space by ID. Args: space_id: The space ID to delete Returns: True if deleted, False if not found """ pass @abstractmethod def exists(self, space_id: str) -> bool: """ Check if a space exists. Args: space_id: The space ID to check Returns: True if exists, False otherwise """ pass @abstractmethod def get_children(self, parent_space_id: str) -> List[InformationSpace]: """ Get all child spaces of a parent space. Args: parent_space_id: The parent space ID Returns: List of child spaces """ pass class IDocumentAssociationRepository(ABC): """ Abstract repository interface for SpaceDocument associations. Manages the relationship between documents and spaces. """ @abstractmethod def add_document(self, document: SpaceDocument) -> SpaceDocument: """ Add a document to a space. Args: document: The document association to create Returns: The created document association Raises: ValueError: If document path already exists in space """ pass @abstractmethod def get_document(self, document_id: str) -> Optional[SpaceDocument]: """ Get a document association by ID. Args: document_id: The document association ID Returns: The document if found, None otherwise """ pass @abstractmethod def get_by_space_path(self, space_id: str, space_path: str) -> Optional[SpaceDocument]: """ Get a document by its path within a space. Args: space_id: The space ID space_path: The path within the space (e.g., "/intro.md") Returns: The document if found, None otherwise """ pass @abstractmethod def list_by_space(self, space_id: str) -> List[SpaceDocument]: """ List all documents in a space. Args: space_id: The space ID Returns: List of documents in the space, ordered by order_index """ pass @abstractmethod def update_document(self, document: SpaceDocument) -> SpaceDocument: """ Update a document association. Args: document: The document with updated values Returns: The updated document Raises: ValueError: If document does not exist """ pass @abstractmethod def remove_document(self, document_id: str) -> bool: """ Remove a document from a space. Args: document_id: The document association ID Returns: True if removed, False if not found """ pass @abstractmethod def move_document(self, document_id: str, new_space_path: str) -> SpaceDocument: """ Move a document to a new path within the space. Args: document_id: The document association ID new_space_path: The new path within the space Returns: The updated document Raises: ValueError: If new path already exists """ pass @abstractmethod def reorder_documents(self, space_id: str, document_ids: List[str]) -> None: """ Reorder documents within a space. Args: space_id: The space ID document_ids: Ordered list of document IDs """ pass @abstractmethod def update_content_hash(self, document_id: str, content_hash: str) -> None: """ Update the content hash for change detection. Args: document_id: The document association ID content_hash: New content hash """ pass class IVariableRepository(ABC): """ Abstract repository interface for SpaceVariable storage. Manages space-level variables for transclusion context. """ @abstractmethod def set_variable(self, variable: SpaceVariable) -> SpaceVariable: """ Set a variable value. Args: variable: The variable to set Returns: The saved variable """ pass @abstractmethod def get_variable(self, space_id: str, name: str) -> Optional[SpaceVariable]: """ Get a variable by name. Args: space_id: The space ID name: Variable name Returns: The variable if found, None otherwise """ pass @abstractmethod def list_variables(self, space_id: str, scope: Optional[str] = None) -> List[SpaceVariable]: """ List all variables in a space. Args: space_id: The space ID scope: Optional scope filter Returns: List of variables """ pass @abstractmethod def delete_variable(self, space_id: str, name: str) -> bool: """ Delete a variable. Args: space_id: The space ID name: Variable name Returns: True if deleted, False if not found """ pass class IReferenceRepository(ABC): """ Abstract repository interface for TransclusionReference tracking. Manages the dependency graph for cache invalidation. """ @abstractmethod def add_reference(self, reference: TransclusionReference) -> TransclusionReference: """ Add a transclusion reference. Args: reference: The reference to add Returns: The saved reference """ pass @abstractmethod def get_references_from(self, source_doc_id: str, space_id: str) -> List[TransclusionReference]: """ Get all references from a source document. Args: source_doc_id: The source document ID space_id: The space ID Returns: List of references from this document """ pass @abstractmethod def get_references_to(self, target_doc_id: str, space_id: str) -> List[TransclusionReference]: """ Get all references to a target document. Args: target_doc_id: The target document ID space_id: The space ID Returns: List of references to this document """ pass @abstractmethod def clear_references_from(self, source_doc_id: str, space_id: str) -> int: """ Clear all references from a source document. Args: source_doc_id: The source document ID space_id: The space ID Returns: Number of references deleted """ pass @abstractmethod def get_dependents(self, document_id: str, space_id: str) -> List[str]: """ Get all documents that depend on a given document. Used for cache invalidation - returns documents that need to be re-rendered when the target document changes. Args: document_id: The document ID space_id: The space ID Returns: List of dependent document IDs """ pass