No canonical snake_case/camelCase serialization policy
This commit is contained in:
@@ -96,7 +96,27 @@ from pydantic import BaseModel, ConfigDict, Field
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class PaginatedListResponse(BaseModel, Generic[T]):
|
||||
class BanGuiBaseModel(BaseModel):
|
||||
"""Project-wide Pydantic base model.
|
||||
|
||||
Enforces the canonical **snake_case** API field naming policy:
|
||||
all JSON wire-format field names use ``snake_case`` on both the backend
|
||||
(Python) and the frontend (TypeScript interfaces). No ``alias_generator``
|
||||
is applied — field names are serialized exactly as written.
|
||||
|
||||
Rules:
|
||||
- Every model in ``app/models/`` must inherit from this class.
|
||||
- Field names must be ``snake_case`` in Python *and* in the JSON payload.
|
||||
- The corresponding TypeScript interface fields must also be ``snake_case``.
|
||||
- Never add a ``camelCase`` alias generator to individual models — any
|
||||
serialization change must go through this base class so all models
|
||||
update at once.
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(strict=True)
|
||||
|
||||
|
||||
class PaginatedListResponse(BanGuiBaseModel, Generic[T]):
|
||||
"""Standardized paginated list response.
|
||||
|
||||
Use this as a base for all endpoints that return paginated collections.
|
||||
@@ -123,15 +143,13 @@ class PaginatedListResponse(BaseModel, Generic[T]):
|
||||
```
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(strict=True)
|
||||
|
||||
items: list[T] = Field(default_factory=list, description="Data items for the current page.")
|
||||
total: int = Field(..., ge=0, description="Total number of items matching the query.")
|
||||
page: int = Field(..., ge=1, description="Current page number (1-based).")
|
||||
page_size: int = Field(..., ge=1, description="Number of items per page.")
|
||||
|
||||
|
||||
class CollectionResponse(BaseModel, Generic[T]):
|
||||
class CollectionResponse(BanGuiBaseModel, Generic[T]):
|
||||
"""Standardized non-paginated collection response.
|
||||
|
||||
Use this for endpoints that return a collection without pagination support.
|
||||
@@ -154,13 +172,11 @@ class CollectionResponse(BaseModel, Generic[T]):
|
||||
```
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(strict=True)
|
||||
|
||||
items: list[T] = Field(default_factory=list, description="Collection items.")
|
||||
total: int = Field(..., ge=0, description="Total number of items.")
|
||||
|
||||
|
||||
class CommandResponse(BaseModel):
|
||||
class CommandResponse(BanGuiBaseModel):
|
||||
"""Standardized command/action result response.
|
||||
|
||||
Use this for endpoints that execute commands (start, stop, reload, ban, unban, etc.).
|
||||
@@ -184,8 +200,6 @@ class CommandResponse(BaseModel):
|
||||
```
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(strict=True)
|
||||
|
||||
message: str = Field(..., description="Human-readable result or error message.")
|
||||
success: bool = Field(
|
||||
default=True,
|
||||
|
||||
Reference in New Issue
Block a user