-
Notifications
You must be signed in to change notification settings - Fork 3
Project Structure
John R. D'Orazio edited this page Feb 9, 2026
·
4 revisions
This page describes the organization of the Axigraph API codebase.
axigraph-api/
├── app/ # Application source code
│ ├── __init__.py
│ ├── main.py # FastAPI application entry point
│ ├── api/ # API routes
│ │ └── v1/ # API version 1
│ │ ├── __init__.py # Router aggregation
│ │ ├── auth.py # Authentication endpoints
│ │ ├── projects.py # Project management
│ │ ├── ontologies.py # Ontology CRUD
│ │ ├── classes.py # OWL class operations
│ │ ├── properties.py # OWL property operations
│ │ └── search.py # Search and SPARQL
│ ├── core/ # Core functionality
│ │ ├── __init__.py
│ │ ├── config.py # Settings (Pydantic)
│ │ ├── database.py # Database connection
│ │ └── auth.py # JWT validation
│ ├── models/ # SQLAlchemy models
│ │ ├── __init__.py # Model exports
│ │ └── project.py # Project, ProjectMember
│ ├── schemas/ # Pydantic schemas
│ │ ├── auth.py # Auth request/response
│ │ ├── project.py # Project schemas
│ │ ├── ontology.py # Ontology schemas
│ │ ├── owl_class.py # OWL class schemas
│ │ ├── owl_property.py # OWL property schemas
│ │ └── search.py # Search schemas
│ ├── services/ # Business logic
│ │ ├── ontology.py # Ontology operations
│ │ ├── project_service.py # Project operations
│ │ └── search.py # Search service
│ ├── collab/ # Collaboration (WebSocket)
│ │ ├── presence.py # User presence
│ │ └── protocol.py # Message protocol
│ └── git/ # Git integration (future)
├── alembic/ # Database migrations
│ ├── env.py # Migration environment
│ ├── script.py.mako # Migration template
│ └── versions/ # Migration files
├── tests/ # Test suite
│ ├── conftest.py # Pytest fixtures
│ └── test_*.py # Test files
├── scripts/ # Utility scripts
│ └── setup-zitadel.py # Zitadel configuration
├── config/ # Configuration files
├── docs/ # Documentation
├── .env # Environment variables (not in git)
├── .env.example # Example environment file
├── alembic.ini # Alembic configuration
├── compose.yaml # Docker Compose for infrastructure
├── Dockerfile # Container build instructions
├── pyproject.toml # Project configuration
└── README.md
The FastAPI application entry point:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI(
title="Axigraph API",
description="Collaborative OWL Ontology Curation Platform",
version="0.1.0",
)
# CORS middleware
app.add_middleware(CORSMiddleware, ...)
# Include API routers
app.include_router(api_v1_router, prefix="/api/v1")Configuration management using Pydantic Settings:
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
app_env: str = "development"
database_url: PostgresDsn
# ... other settings
model_config = SettingsConfigDict(env_file=".env")
settings = get_settings() # Cached singletonAsync SQLAlchemy database setup:
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
class Base(DeclarativeBase):
pass
engine = create_async_engine(str(settings.database_url))
async_session_maker = async_sessionmaker(engine)
async def get_db() -> AsyncGenerator[AsyncSession, None]:
async with async_session_maker() as session:
yield sessionJWT token validation and user extraction:
class CurrentUser(BaseModel):
id: str
email: str | None
name: str | None
roles: list[str] = []
# Dependency injection types
RequiredUser = Annotated[CurrentUser, Depends(get_current_user)]
OptionalUser = Annotated[CurrentUser | None, Depends(get_current_user_optional)]Router aggregation:
from fastapi import APIRouter
router = APIRouter()
router.include_router(auth.router, prefix="/auth", tags=["Authentication"])
router.include_router(projects.router, prefix="/projects", tags=["Projects"])
router.include_router(ontologies.router, prefix="/ontologies", tags=["Ontologies"])
# ... more routers┌──────────────────────────────────────┐
│ API Layer (Routers) │ ← HTTP handling, validation
├──────────────────────────────────────┤
│ Service Layer │ ← Business logic
├──────────────────────────────────────┤
│ Data Layer (Models) │ ← Database operations
└──────────────────────────────────────┘
- Router receives HTTP request
- Pydantic schema validates request body
- Dependencies inject services, user context
- Service executes business logic
- Model interacts with database
- Response schema formats the response
# Router (app/api/v1/projects.py)
@router.post("", response_model=ProjectResponse)
async def create_project(
project: ProjectCreate, # Validated by Pydantic
service: ProjectService = Depends(), # Injected service
user: RequiredUser, # Authenticated user
) -> ProjectResponse:
return await service.create(project, user)
# Service (app/services/project_service.py)
async def create(self, project: ProjectCreate, owner: CurrentUser):
db_project = Project(
name=project.name,
owner_id=owner.id,
...
)
self.db.add(db_project)
await self.db.commit()
return self._to_response(db_project, owner)FastAPI's Depends() is used throughout:
# Database session
def get_db():
return async_session_maker()
# Service with database
def get_project_service(db: AsyncSession = Depends(get_db)):
return ProjectService(db)
# In router
@router.get("/")
async def list(service: ProjectService = Depends(get_project_service)):
...| Type | Convention | Example |
|---|---|---|
| Files | snake_case.py |
project_service.py |
| Classes | PascalCase |
ProjectService |
| Functions | snake_case |
create_project |
| Variables | snake_case |
user_id |
| Constants | UPPER_SNAKE_CASE |
MAX_LIMIT |
| API paths |
kebab-case (usually) or snake_case
|
/api/v1/projects |
For each entity, we typically have:
| Schema | Purpose | Example |
|---|---|---|
{Entity}Base |
Shared fields | ProjectBase |
{Entity}Create |
Input for creation | ProjectCreate |
{Entity}Update |
Input for updates (all optional) | ProjectUpdate |
{Entity}Response |
API response | ProjectResponse |
{Entity}ListResponse |
Paginated list | ProjectListResponse |
# app/models/comment.py
class Comment(Base):
__tablename__ = "comments"
...
# app/models/__init__.py
from .comment import Commentalembic revision --autogenerate -m "Add comments"
alembic upgrade head# app/schemas/comment.py
class CommentCreate(BaseModel): ...
class CommentResponse(BaseModel): ...# app/services/comment_service.py
class CommentService:
def __init__(self, db: AsyncSession):
self.db = db
async def create(self, ...): ...# app/api/v1/comments.py
router = APIRouter()
@router.post("", response_model=CommentResponse)
async def create_comment(...): ...# app/api/v1/__init__.py
router.include_router(comments.router, prefix="/comments", tags=["Comments"])- Development - Development workflow
- Database - Database operations
- API Reference - API documentation