feat(03-01): create project service module
- list_projects() returns all projects ordered by created_at desc - create_project() creates project with default models - get_project() retrieves project by ID Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
e3d72dab60
commit
718dcea7dc
2 changed files with 66 additions and 0 deletions
9
src/moai/core/services/__init__.py
Normal file
9
src/moai/core/services/__init__.py
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
"""Service layer for MoAI business logic.
|
||||||
|
|
||||||
|
Services encapsulate database operations and business rules,
|
||||||
|
providing a clean interface for handlers to use.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from moai.core.services.project import create_project, get_project, list_projects
|
||||||
|
|
||||||
|
__all__ = ["create_project", "get_project", "list_projects"]
|
||||||
57
src/moai/core/services/project.py
Normal file
57
src/moai/core/services/project.py
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
"""Project service for MoAI.
|
||||||
|
|
||||||
|
Provides CRUD operations for projects.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from sqlalchemy import select
|
||||||
|
|
||||||
|
from moai.core.database import get_session
|
||||||
|
from moai.core.models import Project
|
||||||
|
|
||||||
|
DEFAULT_MODELS = ["claude", "gpt", "gemini"]
|
||||||
|
|
||||||
|
|
||||||
|
async def list_projects() -> list[Project]:
|
||||||
|
"""List all projects ordered by creation date (newest first).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of Project objects.
|
||||||
|
"""
|
||||||
|
async with get_session() as session:
|
||||||
|
result = await session.execute(select(Project).order_by(Project.created_at.desc()))
|
||||||
|
return list(result.scalars().all())
|
||||||
|
|
||||||
|
|
||||||
|
async def create_project(name: str, models: list[str] | None = None) -> Project:
|
||||||
|
"""Create a new project.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Human-readable project name.
|
||||||
|
models: List of AI model identifiers. Defaults to ["claude", "gpt", "gemini"].
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The created Project object.
|
||||||
|
"""
|
||||||
|
if models is None:
|
||||||
|
models = DEFAULT_MODELS.copy()
|
||||||
|
|
||||||
|
async with get_session() as session:
|
||||||
|
project = Project(name=name, models=models)
|
||||||
|
session.add(project)
|
||||||
|
await session.flush()
|
||||||
|
await session.refresh(project)
|
||||||
|
return project
|
||||||
|
|
||||||
|
|
||||||
|
async def get_project(project_id: str) -> Project | None:
|
||||||
|
"""Get a project by ID.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
project_id: The project's UUID.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The Project object if found, None otherwise.
|
||||||
|
"""
|
||||||
|
async with get_session() as session:
|
||||||
|
result = await session.execute(select(Project).where(Project.id == project_id))
|
||||||
|
return result.scalar_one_or_none()
|
||||||
Loading…
Add table
Reference in a new issue