diff --git a/AGENTS.md b/AGENTS.md index 18911f4..59cd537 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -34,7 +34,8 @@ - Ponder stores data in `.ponder/`; drop the directory if schema changes break migrations. - Keep git clean before committing; never leave commented-out code or untested changes. - **ES Modules**: The entire stack uses ES modules. kraiken-lib, txnBot, Ponder, and web-app all require `"type": "module"` in package.json and use `import` syntax. -- **Podman Named Volumes**: `kraiken-lib/dist/` is mounted as a named volume (`harb_kraiken-dist`). After changing module format or build configuration, delete the volume with `podman volume rm harb_kraiken-dist` and restart to force a clean rebuild. +- **kraiken-lib Build**: Run `./scripts/build-kraiken-lib.sh` before `podman-compose up` so containers mount a fresh `kraiken-lib/dist` from the host. +- **Live Reload**: `scripts/watch-kraiken-lib.sh` rebuilds on file changes (requires inotify-tools) and restarts dependent containers automatically. ## Handy Commands - `foundryup` - update Foundry toolchain. diff --git a/containers/landing-dev-entrypoint.sh b/containers/landing-dev-entrypoint.sh index d8d3e46..a8c50af 100755 --- a/containers/landing-dev-entrypoint.sh +++ b/containers/landing-dev-entrypoint.sh @@ -3,6 +3,12 @@ set -euo pipefail ROOT_DIR=/workspace LANDING_DIR=$ROOT_DIR/landing +REQUIRED_DIST="$ROOT_DIR/kraiken-lib/dist/index.js" + +if [[ ! -f "$REQUIRED_DIST" ]]; then + echo "[landing-entrypoint] ERROR: Run ./scripts/build-kraiken-lib.sh before starting containers" >&2 + exit 1 +fi cd "$LANDING_DIR" echo "[landing-entrypoint] Installing dependencies..." diff --git a/containers/ponder-dev-entrypoint.sh b/containers/ponder-dev-entrypoint.sh index 73dd0ce..3ef8b1a 100755 --- a/containers/ponder-dev-entrypoint.sh +++ b/containers/ponder-dev-entrypoint.sh @@ -12,6 +12,12 @@ done cd "$PONDER_WORKDIR" +REQUIRED_DIST="$ROOT_DIR/kraiken-lib/dist/index.js" +if [[ ! -f "$REQUIRED_DIST" ]]; then + echo "[ponder-entrypoint] ERROR: Run ./scripts/build-kraiken-lib.sh before starting containers" >&2 + exit 1 +fi + echo "[ponder-entrypoint] Installing dependencies..." npm install --no-save --loglevel error 2>&1 || { echo "[ponder-entrypoint] npm install failed, trying with --force" diff --git a/containers/txn-bot-entrypoint.sh b/containers/txn-bot-entrypoint.sh index ea51568..dbc0624 100755 --- a/containers/txn-bot-entrypoint.sh +++ b/containers/txn-bot-entrypoint.sh @@ -4,42 +4,16 @@ set -euo pipefail ROOT_DIR=/workspace TXNBOT_ENV_FILE=$ROOT_DIR/tmp/podman/txnBot.env BOT_DIR=$ROOT_DIR/services/txnBot -KRAIKEN_LIB_DIR=$ROOT_DIR/kraiken-lib +REQUIRED_DIST=$ROOT_DIR/kraiken-lib/dist/index.js while [[ ! -f "$TXNBOT_ENV_FILE" ]]; do echo "[txn-bot-entrypoint] waiting for env file" sleep 2 done -# Build kraiken-lib first -echo "[txn-bot-entrypoint] Building kraiken-lib..." -cd "$KRAIKEN_LIB_DIR" - -# Install dependencies if needed -if [[ ! -d node_modules ]]; then - echo "[txn-bot-entrypoint] Installing kraiken-lib dependencies..." - npm install --loglevel error -fi - -# Install TypeScript if not present -if [[ ! -f node_modules/.bin/tsc ]]; then - echo "[txn-bot-entrypoint] Installing TypeScript..." - npm install --loglevel error typescript -fi - -# Build TypeScript files (dist is now a volume, writable by node user) -echo "[txn-bot-entrypoint] Compiling TypeScript..." -if [[ ! -f dist/index.js ]]; then - echo "[txn-bot-entrypoint] Running tsc to compile kraiken-lib..." - ./node_modules/.bin/tsc 2>&1 | head -20 || { - echo "[txn-bot-entrypoint] TypeScript compilation had some issues, checking if files were created..." - } - - # Verify the main file exists - if [[ ! -f dist/index.js ]]; then - echo "[txn-bot-entrypoint] ERROR: Failed to compile kraiken-lib" - exit 1 - fi +if [[ ! -f "$REQUIRED_DIST" ]]; then + echo "[txn-bot-entrypoint] ERROR: Run ./scripts/build-kraiken-lib.sh before starting containers" >&2 + exit 1 fi cd "$BOT_DIR" diff --git a/containers/webapp-dev-entrypoint.sh b/containers/webapp-dev-entrypoint.sh index 62ba72e..e0aac82 100755 --- a/containers/webapp-dev-entrypoint.sh +++ b/containers/webapp-dev-entrypoint.sh @@ -11,6 +11,12 @@ while [[ ! -f "$CONTRACT_ENV" ]]; do sleep 2 done +REQUIRED_DIST="$ROOT_DIR/kraiken-lib/dist/index.js" +if [[ ! -f "$REQUIRED_DIST" ]]; then + echo "[frontend-entrypoint] ERROR: Run ./scripts/build-kraiken-lib.sh before starting containers" >&2 + exit 1 +fi + # shellcheck disable=SC1090 source "$CONTRACT_ENV" diff --git a/kraiken-lib/AGENTS.md b/kraiken-lib/AGENTS.md index c9190eb..9293e37 100644 --- a/kraiken-lib/AGENTS.md +++ b/kraiken-lib/AGENTS.md @@ -40,7 +40,7 @@ Shared TypeScript helpers used by the landing app, txnBot, and other services to - `"moduleResolution": "node"` - Enable proper module resolution - `"rootDir": "./src"` - Ensure flat output structure in `dist/` - **Build Output**: Running `npx tsc` produces ES module `.js` files in `dist/` that can be consumed by both browser (Vite) and Node.js (≥14 with `"type": "module"`). -- **Container Volumes**: In Podman/Docker setups, `dist/` is often a named volume. After changing module format or imports, delete the volume (`podman volume rm harb_kraiken-dist`) before restarting to force a clean rebuild. +- **Container Mount**: Podman/Docker services now bind-mount `dist/` read-only from the host. Run `./scripts/build-kraiken-lib.sh` before `podman-compose up` or keep `scripts/watch-kraiken-lib.sh` running to rebuild automatically. ## Quality Guidelines - Keep helpers pure and side-effect free; they should accept explicit dependencies. diff --git a/podman-compose.yml b/podman-compose.yml index afe1387..b54359d 100644 --- a/podman-compose.yml +++ b/podman-compose.yml @@ -49,6 +49,7 @@ services: entrypoint: ["/workspace/containers/ponder-dev-entrypoint.sh"] volumes: - .:/workspace:z + - ./kraiken-lib/dist:/workspace/kraiken-lib/dist:ro,z - ponder-node-modules:/workspace/services/ponder/node_modules working_dir: /workspace environment: @@ -69,6 +70,7 @@ services: entrypoint: ["/workspace/containers/webapp-dev-entrypoint.sh"] volumes: - .:/workspace:z + - ./kraiken-lib/dist:/workspace/kraiken-lib/dist:ro,z - webapp-node-modules:/workspace/web-app/node_modules working_dir: /workspace environment: @@ -86,6 +88,7 @@ services: entrypoint: ["/workspace/containers/landing-dev-entrypoint.sh"] volumes: - .:/workspace:z + - ./kraiken-lib/dist:/workspace/kraiken-lib/dist:ro,z - landing-node-modules:/workspace/landing/node_modules working_dir: /workspace environment: @@ -103,9 +106,9 @@ services: entrypoint: ["/workspace/containers/txn-bot-entrypoint.sh"] volumes: - .:/workspace:z + - ./kraiken-lib/dist:/workspace/kraiken-lib/dist:ro,z - txn-node-modules:/workspace/services/txnBot/node_modules - kraiken-node-modules:/workspace/kraiken-lib/node_modules - - kraiken-dist:/workspace/kraiken-lib/dist working_dir: /workspace depends_on: - anvil @@ -140,4 +143,3 @@ volumes: ponder-node-modules: txn-node-modules: kraiken-node-modules: - kraiken-dist: diff --git a/scripts/build-kraiken-lib.sh b/scripts/build-kraiken-lib.sh new file mode 100755 index 0000000..2e112f3 --- /dev/null +++ b/scripts/build-kraiken-lib.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "$(dirname "$0")/../kraiken-lib" + +if [[ ! -d node_modules || ! -x node_modules/.bin/tsc ]]; then + if ! npm install --silent; then + echo "Warning: npm install failed; continuing with existing node_modules" >&2 + fi +fi + +./node_modules/.bin/tsc + +echo "kraiken-lib built" diff --git a/scripts/watch-kraiken-lib.sh b/scripts/watch-kraiken-lib.sh new file mode 100755 index 0000000..7d2d62b --- /dev/null +++ b/scripts/watch-kraiken-lib.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)" +WATCH_DIR="$ROOT_DIR/kraiken-lib/src" +SERVICES=(harb_ponder_1 harb_webapp_1 harb_landing_1 harb_txn-bot_1) + +if ! command -v inotifywait >/dev/null 2>&1; then + echo "Error: inotifywait not found. Install inotify-tools." >&2 + exit 1 +fi + +if ! command -v podman >/dev/null 2>&1; then + echo "Error: podman not found on PATH." >&2 + exit 1 +fi + +cd "$ROOT_DIR" + +restart_services() { + local missing=0 + local running + mapfile -t running < <(podman ps --format '{{.Names}}') + + for service in "${SERVICES[@]}"; do + local found=1 + for name in "${running[@]}"; do + if [[ "$name" == "$service" ]]; then + found=0 + break + fi + done + + if (( found != 0 )); then + echo "Warning: $service not running; skipping restart" >&2 + missing=1 + continue + fi + + if ! podman restart "$service" >/dev/null; then + echo "Warning: failed to restart $service" >&2 + missing=1 + fi + done + + if [[ $missing -eq 0 ]]; then + echo "Services restarted" + fi +} + +inotifywait -m -r -e close_write,create,delete,moved_to,moved_from "$WATCH_DIR" | +while read -r _directory _events filename; do + echo "kraiken-lib changed: $filename" + ./scripts/build-kraiken-lib.sh + restart_services || true +done diff --git a/services/ponder/AGENTS.md b/services/ponder/AGENTS.md index b9258aa..488fa67 100644 --- a/services/ponder/AGENTS.md +++ b/services/ponder/AGENTS.md @@ -29,7 +29,7 @@ Ponder-based indexer that records Kraiken protocol activity and exposes the Grap - **Virtual Module Errors**: If you see `Failed to load url ponder:registry/ponder:schema/ponder:api`, check: 1. `DATABASE_URL` is properly set and accessible 2. kraiken-lib ABIs exist (`onchain/out/Kraiken.sol/Kraiken.json`) - 3. kraiken-lib TypeScript is built (`kraiken-lib/dist/index.js`) + 3. `./scripts/build-kraiken-lib.sh` has been run so `kraiken-lib/dist/index.js` exists 4. `ponder-env.d.ts` is writable by the container user (chmod 666 or pre-create it) 5. Ponder version is 0.13.8+ (earlier versions had virtual module generation bugs) - **PostgreSQL Connection**: Requires `DATABASE_URL` env var; Ponder falls back to PGlite if not set. The entrypoint must export this before Ponder starts.