# UniSky dev commands. Install just: https://github.com/casey/just
#
# `just --list` shows only the LAST comment line above a recipe, so that line
# is each recipe's one-line summary and any prose goes ABOVE it.

set shell := ["bash", "-uc"]

# THE RECIPES BELOW RUN THIS PROJECT'S OWN TOOLS, AND THEY LIVE IN .venv/bin.
# `unisky` is the console script from `pip install -e .`, and it is what
# frontend/playwright.config.ts starts as its webServer - so on a shell that
# had not activated the venv, `just e2e` (and `just check`, which runs it)
# died before a single test ran:
#
#   [WebServer] /bin/sh: unisky: command not found
#   Error: Process from config.webServer exited early. exit code 127
#
# playwright.config.ts says to run the suite with the project venv on PATH.
# That is a documented precondition nobody can see from `just --list`, and
# `just` is the documented entry point - so the entry point puts it there.
# `python` and `pytest` come along with it: that is the preference `build-fe`
# below already applies to its own interpreter, made once for every recipe.
#
# Harmless when there is no .venv (a PATH entry that is not a directory is
# skipped) and a no-op when the venv is already active, since it is then
# already first.
export PATH := justfile_directory() + "/.venv/bin:" + env_var("PATH")

default: check

# install the python package (editable, dev extras) and frontend deps
setup:
    pip install -e ".[dev]"
    cd frontend && npm install

# python unit tests (realdata tests skip automatically without the volume)
test:
    python -m pytest

# frontend unit tests
test-fe:
    cd frontend && npx vitest run

# THE TWO STEPS ARE ONE COMMAND: `vite build` empties src/unisky/static/, so a
# build without the stamp leaves none, and tests/test_bundle_freshness.py fails
# loudly rather than passing a bundle of unknown age. Commit src/unisky/static/
# with the source change.
# rebuild the viewer bundle into src/unisky/static and stamp it (never a bare `npm run build`)
build-fe:
    cd frontend && npm run build
    # The stamper needs the PROJECT interpreter (it imports pytest), and it
    # runs after `vite build` has already emptied src/unisky/static/ - so a
    # bare `python` that is missing, or is some other environment's, does not
    # merely fail: it leaves no bundle AND no stamp. Prefer the repo's own
    # .venv when there is one; fall back to whatever `python` means, as before.
    PY="{{justfile_directory()}}/.venv/bin/python"; [ -x "$PY" ] || PY=python; \
      "$PY" tests/test_bundle_freshness.py --write

# Offline and instant; the same check the full pytest run makes.
# is the committed viewer bundle the one the committed frontend/ builds?
check-fe-fresh:
    python -m pytest tests/test_bundle_freshness.py -q

# The `unisky` its webServer starts comes from the PATH export at the top of
# this file; without it Playwright exits 127 before the first test.
# Playwright E2E suite over the committed tiny fixture
e2e:
    cd frontend && npm run e2e

# everything CI would run (frontend built first so E2E serves fresh assets)
check: build-fe test test-fe e2e

# A LOCAL config is one whose layers are files on this machine rather than
# archive downloads, so which config is nobody's business but the person
# running it: name it. A full-resolution cluster field is ~10-40 min and
# ~2-4 GB. The public example needs no argument -- see `build-public` below.
# build a site from a local config: `just build-example examples/<name>.yaml`
build-example config out="build-local":
    unisky build {{config}} -o {{out}}

# serve a site built by `build-example` on http://127.0.0.1:8000
serve-example out="build-local":
    unisky serve {{out}} --host 127.0.0.1 --port 8000

# Public, and the one anybody can run: everything is downloaded and cached.
# build the public Abell 2744 example (network; ~30 s cold, ~2 s warm, 14 MB)
build-public:
    unisky build examples/abell2744.yaml -o build-a2744

# serve the public Abell 2744 example on http://127.0.0.1:8000
serve-public:
    unisky serve build-a2744 --host 127.0.0.1 --port 8000

# ---------------------------------------------------------------- unisky.cc
# www/ is a plain static site (index.html, docs.html, assets/) plus the paper
# PDF. It is served as-is; `site-artifacts` folds each page into ONE
# self-contained file for hosts that want a single upload.

# compile paper/unisky.tex and drop the PDF where the site links to it
paper:
    cd paper && latexmk -pdf -interaction=nonstopmode unisky.tex
    cp paper/unisky.pdf www/paper.pdf

# preview the unisky.cc site on http://127.0.0.1:8999
serve-site:
    cd www && python -m http.server 8999 --bind 127.0.0.1

# fold each page into one self-contained HTML file under dist-site/
site-artifacts:
    python www/build_artifact.py index.html -o dist-site/unisky-landing.html
    python www/build_artifact.py docs.html  -o dist-site/unisky-docs.html
