Add full sortof codebase: API, drain workers, frontend, schema, specs

This commit is contained in:
2026-05-04 03:27:54 +00:00
parent acda2c90f8
commit 55d3794bfb
43 changed files with 13375 additions and 53 deletions

View File

@@ -1,68 +1,52 @@
# sortof
A Project Zomboid mod load-order sorter. Paste Steam Workshop IDs or a
collection URL, get back the three lines (`WorkshopItems=`, `Mods=`,
`Map=`) you paste into your dedicated server's `.ini` file.
Project Zomboid mod load-order sorter for dedicated servers. Paste workshop
IDs or a collection URL; get back the `WorkshopItems=`, `Mods=`, and `Map=`
lines for `servertest.ini`.
## Stack
- **API** — FastAPI + asyncpg, Python 3.12.
- **Cache** — PostgreSQL 16. One row per `(workshop_id, mod_id)` parsed
from each mod's `mod.info`. Cache invalidates on Steam's
`time_updated`; no manual TTLs.
- **Drain worker** — pulls cache misses via DepotDownloader, parses
`mod.info` and `media/maps/*/map.info`, writes back to Postgres.
- **Frontend** — vanilla JSX in `frontend/`, served by FastAPI
`StaticFiles`, transpiled in-browser by Babel-standalone. No build
step, no npm.
- **Deployment** — Docker for Postgres only; the API and drain workers
run as systemd units on the host.
- FastAPI + asyncpg, Python 3.12.
- Postgres 16 (Docker).
- DepotDownloader for fetching `mod.info` / `map.info` from each cached
workshop item.
- Vanilla JSX + index.html, no build step (Babel-standalone in-browser).
## What it actually does
## Setup
- Resolves bare workshop IDs **and** collection URLs (anonymous Steam API
expansion).
- Topologically sorts mods by `requirements`, `loadAfter`, `loadBefore`
with explicit support for `loadFirst` / `loadLast` and the "patch"
tier.
- Detects multi-branch wsids (e.g. AuthenticZ, Project RV Interior),
auto-picks a sensible default by build flavor or input cross-reference,
and surfaces the alternates in a picker.
- Emits actionable warnings: missing dependencies (with one-click "add"
buttons when the dep is in our cache), build-mismatch flags with
swap-or-remove actions, duplicate-mod_id conflicts, addon detection,
and required-item suggestions scraped from the Workshop page.
- Tracks community-reported broken mods per PZ build, with thumbs-up /
thumbs-down voting and a search panel.
```bash
docker compose up -d sortof_db
## Bootstrapping (rough)
python3.12 -m venv api/.venv
api/.venv/bin/pip install -r api/requirements.txt
1. `docker compose up -d sortof_db` — runs Postgres on `127.0.0.1:5439`,
applies `init/*.sql` migrations on first boot.
2. Create the two virtualenvs:
```bash
python3.12 -m venv api/.venv && api/.venv/bin/pip install -r api/requirements.txt
python3.12 -m venv worker/.venv && worker/.venv/bin/pip install -r worker/requirements.txt
```
3. Drop a `.env` next to `docker-compose.yml` with `POSTGRES_USER`,
`POSTGRES_PASSWORD`, `POSTGRES_DB`, and `SORTOF_CORS_ORIGINS`.
4. Set `DD_PATH` to wherever DepotDownloader lives, then start the API
(`api/.venv/bin/uvicorn app:app --host 127.0.0.1 --port 8801`) and a
drain worker (`worker/.venv/bin/python drain.py`).
python3.12 -m venv worker/.venv
worker/.venv/bin/pip install -r worker/requirements.txt
```
For the systemd units, see `docs/` (and the running host).
`.env` next to `docker-compose.yml`:
```
POSTGRES_USER=sortof
POSTGRES_PASSWORD=<random>
POSTGRES_DB=sortof
SORTOF_CORS_ORIGINS=http://127.0.0.1:8801
```
Set `DD_PATH` to the DepotDownloader binary, then:
```bash
api/.venv/bin/uvicorn app:app --host 127.0.0.1 --port 8801
worker/.venv/bin/python drain.py
```
## Layout
```
api/ FastAPI service + adapters + sort engine
worker/ drain worker DepotDownloader + mod.info parser
frontend/ vanilla JSX + index.html (no build step)
init/ Postgres bootstrap migrations (runs in order)
data/ checked-in JSON like pz_versions.json
docs/ specs, plans, audit notes
api/ FastAPI service, sort engine, response adapters
worker/ drain worker (DepotDownloader + mod.info parser)
frontend/ index.html + JSX
init/ Postgres bootstrap migrations (run on first boot)
data/ checked-in JSON config (e.g., pz_versions.json)
docs/ specs, plans
```
## License
TBD.