WIP checkpoint: Scaffold FastAPI backend project structure
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
# Database
|
# Database (async driver)
|
||||||
DATABASE_URL=postgresql://agp_user:agp_password@localhost:5432/agp_db
|
DATABASE_URL=postgresql+asyncpg://agp_user:agp_password@localhost:5432/agp_db
|
||||||
|
|
||||||
# Redis
|
# Redis
|
||||||
REDIS_URL=redis://localhost:6379/0
|
REDIS_URL=redis://localhost:6379/0
|
||||||
@@ -10,5 +10,11 @@ ALGORITHM=HS256
|
|||||||
ACCESS_TOKEN_EXPIRE_MINUTES=30
|
ACCESS_TOKEN_EXPIRE_MINUTES=30
|
||||||
|
|
||||||
# App
|
# App
|
||||||
|
APP_NAME=AGP Backend
|
||||||
|
APP_VERSION=0.1.0
|
||||||
DEBUG=true
|
DEBUG=true
|
||||||
CORS_ORIGINS=http://localhost:8080,http://localhost:3000
|
CORS_ORIGINS=http://localhost:8080,http://localhost:3000
|
||||||
|
|
||||||
|
# File uploads
|
||||||
|
UPLOAD_DIR=uploads
|
||||||
|
MAX_UPLOAD_SIZE_MB=100
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ class Settings(BaseSettings):
|
|||||||
env_file=".env",
|
env_file=".env",
|
||||||
env_file_encoding="utf-8",
|
env_file_encoding="utf-8",
|
||||||
case_sensitive=True,
|
case_sensitive=True,
|
||||||
extra="ignore",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
+13
-3
@@ -3,6 +3,7 @@
|
|||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
|
||||||
from app.config import settings
|
from app.config import settings
|
||||||
from app.routers import auth, users, worlds, assets
|
from app.routers import auth, users, worlds, assets
|
||||||
@@ -17,12 +18,21 @@ async def lifespan(app: FastAPI):
|
|||||||
|
|
||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
title=settings.app_name,
|
title=settings.APP_NAME,
|
||||||
version=settings.app_version,
|
version=settings.APP_VERSION,
|
||||||
description="Agentic Game Platform - Backend API",
|
description="Agentic Game Platform - Backend API",
|
||||||
lifespan=lifespan,
|
lifespan=lifespan,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# CORS
|
||||||
|
app.add_middleware(
|
||||||
|
CORSMiddleware,
|
||||||
|
allow_origins=settings.cors_origins_list,
|
||||||
|
allow_credentials=True,
|
||||||
|
allow_methods=["*"],
|
||||||
|
allow_headers=["*"],
|
||||||
|
)
|
||||||
|
|
||||||
# Include routers
|
# Include routers
|
||||||
app.include_router(auth.router, prefix="/api/auth", tags=["auth"])
|
app.include_router(auth.router, prefix="/api/auth", tags=["auth"])
|
||||||
app.include_router(users.router, prefix="/api/users", tags=["users"])
|
app.include_router(users.router, prefix="/api/users", tags=["users"])
|
||||||
@@ -33,4 +43,4 @@ app.include_router(assets.router, prefix="/api/assets", tags=["assets"])
|
|||||||
@app.get("/api/health")
|
@app.get("/api/health")
|
||||||
async def health_check():
|
async def health_check():
|
||||||
"""Simple health check endpoint."""
|
"""Simple health check endpoint."""
|
||||||
return {"status": "ok", "app": settings.app_name}
|
return {"status": "ok", "app": settings.APP_NAME}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Boolean
|
import uuid
|
||||||
|
|
||||||
|
from sqlalchemy import Column, String, DateTime, ForeignKey, Boolean
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
from sqlalchemy.sql import func
|
from sqlalchemy.sql import func
|
||||||
from app.database import Base
|
from app.database import Base
|
||||||
@@ -7,7 +9,7 @@ from app.database import Base
|
|||||||
class Session(Base):
|
class Session(Base):
|
||||||
__tablename__ = "sessions"
|
__tablename__ = "sessions"
|
||||||
|
|
||||||
id = Column(String, primary_key=True)
|
id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
||||||
user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
|
user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
|
||||||
token = Column(String, unique=True, index=True, nullable=False)
|
token = Column(String, unique=True, index=True, nullable=False)
|
||||||
expires_at = Column(DateTime(timezone=True), nullable=False)
|
expires_at = Column(DateTime(timezone=True), nullable=False)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, Enum
|
from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey
|
||||||
|
from sqlalchemy.dialects.postgresql import ENUM
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
from sqlalchemy.sql import func
|
from sqlalchemy.sql import func
|
||||||
import enum
|
import enum
|
||||||
@@ -19,7 +20,10 @@ class World(Base):
|
|||||||
name = Column(String(255), nullable=False)
|
name = Column(String(255), nullable=False)
|
||||||
description = Column(Text, nullable=True)
|
description = Column(Text, nullable=True)
|
||||||
owner_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
owner_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||||
visibility = Column(Enum(WorldVisibility), default=WorldVisibility.PUBLIC)
|
visibility = Column(
|
||||||
|
ENUM(WorldVisibility, name="world_visibility", create_type=False),
|
||||||
|
default=WorldVisibility.PUBLIC,
|
||||||
|
)
|
||||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||||
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user