Skip to content

ports_secondary

Define how the domain interacts with infrastructure.

GoogleTokenVerifierPort

Secondary port for verifying Google ID tokens.

verify abstractmethod

verify(id_token: str) -> GoogleUserInfo

Verify a Google ID token and return user info.

RAISES DESCRIPTION
ValueError

If the token is invalid or expired.

ImageStoragePort

add_recipe_image abstractmethod

add_recipe_image(recipe_id: UUID, image: bytes, filename: str, image_id: UUID) -> UUID

Add an image to storage and return its image ID.

delete_image abstractmethod

delete_image(image_id: UUID) -> bool

Delete an image file from storage. Returns True if deleted, False if not found.

get_recipe_image abstractmethod

get_recipe_image(image_id: UUID) -> ImageResponse | None

Retrieve image bytes from storage by image ID.

InstagramParserPort

Secondary port for parsing Instagram export data into recipe schemas.

parse abstractmethod

parse(data: InstagramResponse) -> list[ParsedRecipe]

Parse validated Instagram data into recipes with image URLs.

JwtTokenPort

Secondary port for JWT token operations.

create_access_token abstractmethod

create_access_token(user_id: UUID) -> str

Create a JWT access token for the given user ID.

decode_access_token abstractmethod

decode_access_token(token: str) -> UUID

Decode a JWT access token and return the user ID.

RAISES DESCRIPTION
ValueError

If the token is invalid or expired.

MarkdownExporterPort

Secondary port for Markdown format export.

save abstractmethod

save(recipes: list[RecipeEntity], output_file: str) -> None

Save recipes to a Markdown file (includes I/O side effect).

to_string abstractmethod

to_string(recipes: list[RecipeEntity]) -> str

Serialize recipes to Markdown string format.

to_zip_bytes abstractmethod

to_zip_bytes(recipes: list[RecipeEntity]) -> bytes

Serialize recipes to a ZIP archive containing the Markdown file and images.

RecipeRepositoryPort

Secondary port for recipe persistence.

Abstraction for database operations. The domain doesn't care if it's SQLAlchemy, MongoDB, or any other persistence mechanism.

add_image abstractmethod

add_image(
    recipe_id: UUID,
    user_id: UUID,
    caption: str | None = None,
    display_order: int | None = 0,
) -> ImageEntity

Persist an Image record for a recipe owned by user_id.

add_recipe abstractmethod

add_recipe(data: RecipeCreate, owner_id: UUID) -> RecipeEntity

Persist a new recipe and return it as a domain entity.

add_recipes abstractmethod

add_recipes(data: list[RecipeCreate], owner_id: UUID) -> list[RecipeEntity]

Persist multiple recipes atomically and return them as domain entities.

delete_image abstractmethod

delete_image(image_id: UUID, user_id: UUID) -> bool

Delete an Image record by ID. Returns True if deleted, False if not found/owned.

delete_recipe abstractmethod

delete_recipe(recipe_id: UUID, user_id: UUID) -> bool

Delete a recipe by ID. Returns True if deleted, False if not found/owned.

get_recipe_by_id abstractmethod

get_recipe_by_id(recipe_id: UUID, user_id: UUID) -> RecipeEntity | None

Retrieve a recipe by ID, scoped to the given user.

image_belongs_to_user abstractmethod

image_belongs_to_user(image_id: UUID, user_id: UUID) -> bool

Check if an image belongs to a recipe owned by the given user.

search_recipes abstractmethod

search_recipes(
    user_id: UUID,
    recipe_id: UUID | None = None,
    title: str | None = None,
    category: str | None = None,
    is_veggie: bool | None = None,
    season: str | None = None,
    limit: int | None = None,
    offset: int = 0,
    ownership: str | None = None,
) -> PaginatedResult

Query recipes with dynamic filtering and pagination, visible to the given user.

update_recipe abstractmethod

update_recipe(
    recipe_id: UUID, data: RecipeUpdate, user_id: UUID
) -> RecipeEntity | None

Full replacement of a recipe. Returns None if not found or not owned.

RecipeShareRepositoryPort

Secondary port for recipe share persistence.

accept_all_pending_shares abstractmethod

accept_all_pending_shares(user_id: UUID) -> list[RecipeShareEntity]

Accept all pending shares for a user in a single transaction.

create_share abstractmethod

create_share(
    recipe_id: UUID, shared_by_user_id: UUID, shared_with_user_id: UUID, role: ShareRole
) -> RecipeShareEntity

Create a new share invitation.

delete_share abstractmethod

delete_share(share_id: UUID) -> bool

Delete a share record. Returns True if deleted.

get_pending_shares_count abstractmethod

get_pending_shares_count(user_id: UUID) -> int

Count pending share invitations for a user.

get_pending_shares_for_user abstractmethod

get_pending_shares_for_user(user_id: UUID) -> list[RecipeShareEntity]

List all pending share invitations for a user.

get_share_by_id abstractmethod

get_share_by_id(share_id: UUID) -> RecipeShareEntity | None

Retrieve a share by its ID.

get_share_for_recipe_and_user abstractmethod

get_share_for_recipe_and_user(
    recipe_id: UUID, user_id: UUID
) -> RecipeShareEntity | None

Get the share record for a specific recipe and user.

get_shares_for_recipe abstractmethod

get_shares_for_recipe(recipe_id: UUID) -> list[RecipeShareEntity]

List all shares (any status) for a recipe.

get_user_role_for_recipe abstractmethod

get_user_role_for_recipe(recipe_id: UUID, user_id: UUID) -> str | None

Return 'owner', 'editor', 'reader', or None if no access.

update_share_status abstractmethod

update_share_status(share_id: UUID, status: ShareStatus) -> RecipeShareEntity | None

Update the status of a share invitation.

UserRepositoryPort

Secondary port for user persistence.

create_user abstractmethod

create_user(
    email: str,
    display_name: str,
    auth_provider: AuthProvider,
    auth_provider_id: str,
    avatar_url: str | None = None,
) -> UserEntity

Create a new user and return the domain entity.

get_user_by_email abstractmethod

get_user_by_email(email: str) -> UserEntity | None

Retrieve a user by email address.

get_user_by_id abstractmethod

get_user_by_id(user_id: UUID) -> UserEntity | None

Retrieve a user by ID.

get_user_by_provider abstractmethod

get_user_by_provider(
    auth_provider: AuthProvider, auth_provider_id: str
) -> UserEntity | None

Retrieve a user by SSO provider and provider-specific ID.

WordExporterPort

Secondary port for Word format export.

save abstractmethod

save(recipes: list[RecipeEntity], output_path: str) -> None

Save recipes to a Word file.

to_bytes abstractmethod

to_bytes(recipes: list[RecipeEntity]) -> bytes

Serialize recipes to Word binary format.