- Add ORCHARD_ENV setting (defaults to 'development') - Add seed.py with test projects, packages, artifacts, and tags - Automatically seed database on startup in development mode - Skip seeding if database already contains data - Skip seeding in production mode (ORCHARD_ENV=production) Test data includes: - 4 projects (3 public, 1 private) - 8 packages across projects - 5 artifacts with various content types - 10 tags including version tags and 'latest'
71 lines
2.1 KiB
Python
71 lines
2.1 KiB
Python
from fastapi import FastAPI
|
|
from fastapi.staticfiles import StaticFiles
|
|
from fastapi.responses import FileResponse
|
|
from contextlib import asynccontextmanager
|
|
import logging
|
|
import os
|
|
|
|
from .config import get_settings
|
|
from .database import init_db, SessionLocal
|
|
from .routes import router
|
|
from .seed import seed_database
|
|
|
|
settings = get_settings()
|
|
logging.basicConfig(level=logging.INFO)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
# Startup: initialize database
|
|
init_db()
|
|
|
|
# Seed test data in development mode
|
|
if settings.is_development:
|
|
logger.info(f"Running in {settings.env} mode - checking for seed data")
|
|
db = SessionLocal()
|
|
try:
|
|
seed_database(db)
|
|
finally:
|
|
db.close()
|
|
else:
|
|
logger.info(f"Running in {settings.env} mode - skipping seed data")
|
|
|
|
yield
|
|
# Shutdown: cleanup if needed
|
|
|
|
|
|
app = FastAPI(
|
|
title="Orchard",
|
|
description="Content-Addressable Storage System",
|
|
version="1.0.0",
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
# Include API routes
|
|
app.include_router(router)
|
|
|
|
# Serve static files (React build) if the directory exists
|
|
static_dir = os.path.join(os.path.dirname(__file__), "..", "..", "frontend", "dist")
|
|
if os.path.exists(static_dir):
|
|
app.mount("/assets", StaticFiles(directory=os.path.join(static_dir, "assets")), name="assets")
|
|
|
|
@app.get("/")
|
|
async def serve_spa():
|
|
return FileResponse(os.path.join(static_dir, "index.html"))
|
|
|
|
# Catch-all for SPA routing (must be last)
|
|
@app.get("/{full_path:path}")
|
|
async def serve_spa_routes(full_path: str):
|
|
# Don't catch API routes
|
|
if full_path.startswith("api/") or full_path.startswith("health") or full_path.startswith("project/"):
|
|
from fastapi import HTTPException
|
|
raise HTTPException(status_code=404, detail="Not found")
|
|
|
|
index_path = os.path.join(static_dir, "index.html")
|
|
if os.path.exists(index_path):
|
|
return FileResponse(index_path)
|
|
|
|
from fastapi import HTTPException
|
|
raise HTTPException(status_code=404, detail="Not found")
|