feat: add standards wiki, MCP registry, and app template
This commit is contained in:
0
templates/app/infra/adapters/__init__.py
Normal file
0
templates/app/infra/adapters/__init__.py
Normal file
128
templates/app/infra/adapters/service.py
Normal file
128
templates/app/infra/adapters/service.py
Normal file
@@ -0,0 +1,128 @@
|
||||
"""# Summary
|
||||
|
||||
Generic CRUD service adaptor over a Mongo repository.
|
||||
|
||||
Bridge pydantic models and mongo-ops documents, exposing create, read, update,
|
||||
patch, delete, and search operations for every domain that needs them.
|
||||
"""
|
||||
from typing import Generic, Type, TypeVar
|
||||
|
||||
from infra.db.repos import mongo
|
||||
|
||||
from pydantic import BaseModel
|
||||
from mongo_ops import BaseDocument
|
||||
from mongo_ops.models import PyObjectId
|
||||
|
||||
Model = TypeVar("Model", bound=BaseModel)
|
||||
Schema = TypeVar("Schema", bound=BaseDocument)
|
||||
|
||||
|
||||
class CrudsServiceAdaptor(Generic[Model, Schema]):
|
||||
"""Adapt a generic Mongo repository to a model/schema CRUD service.
|
||||
|
||||
Attributes:
|
||||
repo (mongo.BaseRepository): Repository backing all CRUD operations.
|
||||
model (Type[Model]): Pydantic model type handled by this service.
|
||||
schema (Type[Schema]): Document schema type persisted by the repository.
|
||||
"""
|
||||
|
||||
repo: mongo.BaseRepository
|
||||
model: Type[Model]
|
||||
schema: Type[Schema]
|
||||
|
||||
def __init__(self, *, repo=None):
|
||||
"""Initialize the adaptor with a backing repository.
|
||||
|
||||
Args:
|
||||
repo (mongo.BaseRepository): Repository used for all operations.
|
||||
"""
|
||||
self.repo = repo
|
||||
|
||||
@staticmethod
|
||||
def model_to_dict(model_obj: Model) -> dict:
|
||||
"""Serialize a model into a sparse dictionary.
|
||||
|
||||
Args:
|
||||
model_obj (Model): Model instance to serialize.
|
||||
|
||||
Returns:
|
||||
dict: Fields that are set and not ``None``.
|
||||
"""
|
||||
return model_obj.model_dump(exclude_unset=True, exclude_none=True)
|
||||
|
||||
async def create(self, data: Model | dict) -> Schema:
|
||||
"""Create a document from a model or raw mapping.
|
||||
|
||||
Args:
|
||||
data (Model | dict): Model instance or field mapping to persist.
|
||||
|
||||
Returns:
|
||||
Schema: Persisted document.
|
||||
"""
|
||||
if isinstance(data, dict):
|
||||
data = self.schema(**data)
|
||||
return await self.repo.create(data)
|
||||
|
||||
async def read(self, id: PyObjectId) -> Schema | None:
|
||||
"""Read a document by primary key.
|
||||
|
||||
Args:
|
||||
id (PyObjectId): Document identifier.
|
||||
|
||||
Returns:
|
||||
Schema | None: Matching document, or ``None`` when absent.
|
||||
"""
|
||||
return await self.repo.get_by_id(id)
|
||||
|
||||
async def update(self, id: PyObjectId, data: Model | dict) -> Schema | None:
|
||||
"""Replace a document by primary key.
|
||||
|
||||
Args:
|
||||
id (PyObjectId): Document identifier.
|
||||
data (Model | dict): Replacement model or field mapping.
|
||||
|
||||
Returns:
|
||||
Schema | None: Updated document, or ``None`` when absent.
|
||||
"""
|
||||
return await self.repo.update(
|
||||
id,
|
||||
data if isinstance(data, dict) else self.model_to_dict(data),
|
||||
)
|
||||
|
||||
async def patch(self, id: PyObjectId, data: dict) -> Schema | None:
|
||||
"""Partially update a document by primary key.
|
||||
|
||||
Args:
|
||||
id (PyObjectId): Document identifier.
|
||||
data (dict): Fields to patch.
|
||||
|
||||
Returns:
|
||||
Schema | None: Updated document, or ``None`` when absent.
|
||||
"""
|
||||
return await self.repo.patch(id, data)
|
||||
|
||||
async def delete(self, id: PyObjectId) -> bool:
|
||||
"""Delete a document by primary key.
|
||||
|
||||
Args:
|
||||
id (PyObjectId): Document identifier.
|
||||
|
||||
Returns:
|
||||
bool: ``True`` when a document was deleted.
|
||||
"""
|
||||
return await self.repo.delete(id)
|
||||
|
||||
async def search(self, filter: dict | None = None, *args, **kwargs) -> list[Schema]:
|
||||
"""List documents matching an optional filter.
|
||||
|
||||
Args:
|
||||
filter (dict | None): Query filter passed to the repository.
|
||||
|
||||
Returns:
|
||||
list[Schema]: Matching documents.
|
||||
|
||||
Notes:
|
||||
Extra positional and keyword arguments are forwarded to the
|
||||
repository.
|
||||
"""
|
||||
return await self.repo.get_many(filter=filter, *args, **kwargs)
|
||||
Reference in New Issue
Block a user