set shell := ["bash", "-cu"] backend := "backend" db_url := "postgresql+asyncpg://fintracker:fintracker@localhost:54329/fintracker" default: @just --list # --- python --- # install backend deps (uv) sync: cd {{backend}} && uv sync # run API with reload against the local dev DB api: cd {{backend}} && DATABASE_URL={{db_url}} ALLOW_DEV_SECRET=1 uv run fintracker serve --reload # API + Flutter web build from one origin (run `just build-web` first) web: cd {{backend}} && DATABASE_URL={{db_url}} ALLOW_DEV_SECRET=1 WEB_DIR=../app/build/web uv run fintracker serve --port 8000 # db + migrations + Flutter web build + API and web on :8000 (needs `nix develop .#app`) dev: db-start migrate build-web web # --- flutter --- build-web: cd app && flutter pub get && flutter build web --release # fetch sqlite3.wasm + compile drift_worker.js into app/web/ (offline cache, drift/wasm+OPFS — # see docs/ai/offline-cache.md). Re-run whenever the drift/sqlite3 package versions change; # both files are committed, so this is not needed on every build. app-web-assets: cd app && flutter pub get v=$(cd app && flutter pub deps --json | jq -r '.packages[] | select(.name=="sqlite3") | .version') && \ curl -fL -o app/web/sqlite3.wasm "https://github.com/simolus3/sqlite3.dart/releases/download/sqlite3-$v/sqlite3.wasm" d=$(jq -r '.packages[] | select(.name=="drift") | .rootUri' app/.dart_tool/package_config.json | sed 's#^file://##') && \ cd app && dart compile js -O2 --packages=.dart_tool/package_config.json -o web/drift_worker.js "$d/web/drift_worker.dart" && \ rm -f web/drift_worker.js.deps web/drift_worker.js.map app-check: cd app && flutter pub get && flutter analyze && flutter test # one-off source sync against the local dev DB (zenmoney | cbr) pull SOURCE: cd {{backend}} && DATABASE_URL={{db_url}} uv run fintracker sync {{SOURCE}} # run the sync worker against the local dev DB worker: cd {{backend}} && DATABASE_URL={{db_url}} uv run fintracker worker lint: cd {{backend}} && uv run ruff check . && uv run ruff format --check . fmt: cd {{backend}} && uv run ruff format . && uv run ruff check --fix . typecheck: cd {{backend}} && uv run pyright test *ARGS: cd {{backend}} && uv run pytest {{ARGS}} check: lint typecheck test openapi-check app-check # --- database (local dev cluster in ./.pgdata, port 54329) --- db-init: test -d .pgdata || initdb -D .pgdata -U postgres --auth=trust --no-locale --encoding=UTF8 >/dev/null grep -q "unix_socket_directories = '$PWD/.pgdata'" .pgdata/postgresql.conf || \ printf "\nport = 54329\nunix_socket_directories = '%s/.pgdata'\nlisten_addresses = 'localhost'\n" "$PWD" >> .pgdata/postgresql.conf db-start: db-init pg_ctl -D .pgdata status >/dev/null 2>&1 || pg_ctl -D .pgdata -l .pgdata/log start -w psql -h localhost -p 54329 -U postgres -tc "SELECT 1 FROM pg_roles WHERE rolname='fintracker'" | grep -q 1 || \ psql -h localhost -p 54329 -U postgres -c "CREATE ROLE fintracker LOGIN PASSWORD 'fintracker' CREATEDB" psql -h localhost -p 54329 -U postgres -tc "SELECT 1 FROM pg_database WHERE datname='fintracker'" | grep -q 1 || \ psql -h localhost -p 54329 -U postgres -c "CREATE DATABASE fintracker OWNER fintracker" db-stop: pg_ctl -D .pgdata status >/dev/null 2>&1 && pg_ctl -D .pgdata stop -m fast || true db-psql: psql -h localhost -p 54329 -U fintracker fintracker migrate *ARGS="upgrade head": cd {{backend}} && DATABASE_URL={{db_url}} uv run alembic {{ARGS}} # create a new migration from model changes revision MSG: cd {{backend}} && DATABASE_URL={{db_url}} uv run alembic revision --autogenerate -m "{{MSG}}" create-user EMAIL: cd {{backend}} && DATABASE_URL={{db_url}} uv run fintracker create-user {{EMAIL}} # --- openapi / dart client --- # export openapi/openapi.json from the FastAPI app openapi: cd {{backend}} && uv run fintracker openapi ../openapi/openapi.json # fail if the committed spec drifted from the code openapi-check: cd {{backend}} && uv run fintracker openapi /tmp/fin-tracker-openapi.json diff -q openapi/openapi.json /tmp/fin-tracker-openapi.json # regenerate app/packages/api_client from openapi/openapi.json gen-client: openapi rm -rf app/packages/api_client/lib app/packages/api_client/doc openapi-generator-cli generate -g dart-dio -i openapi/openapi.json -o app/packages/api_client \ -c app/packages/api_client/openapi-config.yaml # the generator pins an old language version; null-aware elements need >= 3.8 sed -i "s/sdk: '>=3.5.0 <4.0.0'/sdk: '>=3.8.0 <4.0.0'/" app/packages/api_client/pubspec.yaml cd app/packages/api_client && dart pub get && dart run build_runner build --delete-conflicting-outputs # --- deploy (VPS) --- # build without the host proxy vars: podman/buildah bakes HTTP_PROXY into the image otherwise up: env -u http_proxy -u https_proxy -u HTTP_PROXY -u HTTPS_PROXY -u ALL_PROXY -u all_proxy \ docker compose up -d --build logs *ARGS: docker compose logs -f {{ARGS}}