Initial commit
This commit is contained in:
77
backend/app/main.py
Normal file
77
backend/app/main.py
Normal file
@@ -0,0 +1,77 @@
|
||||
from fastapi import FastAPI
|
||||
|
||||
from .router import router
|
||||
from .recipes_router import router as recipes_router
|
||||
from .database import engine
|
||||
from sqlalchemy import text
|
||||
|
||||
app = FastAPI(title="FFXI Item Browser API")
|
||||
|
||||
# Ensure all_items view exists on startup
|
||||
@app.on_event("startup")
|
||||
async def ensure_view():
|
||||
"""Recreate the materialized view `all_items` each startup to ensure schema consistency.
|
||||
The view merges all *_items tables and exposes columns: id, name, description, icon_id, type_description.
|
||||
Some source tables may lack `description` or `icon_id`; NULLs are substituted in those cases.
|
||||
"""
|
||||
async with engine.begin() as conn:
|
||||
# Drop existing view if present
|
||||
await conn.execute(text("DROP VIEW IF EXISTS all_items"))
|
||||
|
||||
# Discover item tables
|
||||
table_rows = await conn.execute(
|
||||
text(
|
||||
"SELECT tablename FROM pg_tables WHERE schemaname='public'"
|
||||
" AND tablename LIKE '%_items' AND tablename NOT IN ('inventory')"
|
||||
)
|
||||
)
|
||||
tables = [r[0] for r in table_rows]
|
||||
if not tables:
|
||||
return
|
||||
|
||||
selects = []
|
||||
for t in tables:
|
||||
desc_exists = await conn.scalar(
|
||||
text(
|
||||
"""
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name=:table AND column_name='description'
|
||||
)
|
||||
"""),
|
||||
{"table": t},
|
||||
)
|
||||
icon_exists = await conn.scalar(
|
||||
text(
|
||||
"""
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_name=:table AND column_name='icon_id'
|
||||
)
|
||||
"""),
|
||||
{"table": t},
|
||||
)
|
||||
desc_col = "description" if desc_exists else "NULL"
|
||||
icon_col = "icon_id" if icon_exists else "NULL"
|
||||
selects.append(
|
||||
f"SELECT id, name, {desc_col} AS description, {icon_col} AS icon_id, type_description FROM {t}"
|
||||
)
|
||||
|
||||
union_sql = " UNION ALL ".join(selects)
|
||||
await conn.execute(text(f"CREATE VIEW all_items AS {union_sql}"))
|
||||
await conn.commit()
|
||||
|
||||
# Mount API routes
|
||||
app.include_router(router, prefix="/api")
|
||||
app.include_router(recipes_router, prefix="/api")
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
async def health():
|
||||
return {"status": "ok"}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run("app.main:app", host="0.0.0.0", port=8000, reload=True)
|
||||
Reference in New Issue
Block a user