658 lines
30 KiB
Bash
Executable file
658 lines
30 KiB
Bash
Executable file
#!/bin/bash
|
|
# Dev environment commands for lilith-platform.live
|
|
# Sourced by the top-level ./run script — do not execute directly.
|
|
# SCRIPT_DIR and ROOT_DIR are set by the caller.
|
|
|
|
COMMAND="${1:-dev}"
|
|
|
|
case "$COMMAND" in
|
|
dev)
|
|
echo "Starting lilith-platform.live dev environment..."
|
|
docker compose -f "$ROOT_DIR/deployments/docker/docker-compose.yml" up -d
|
|
echo "PostgreSQL (waitlist) running on port 25460"
|
|
echo "PostgreSQL (merchant) running on port 25445"
|
|
echo ""
|
|
|
|
echo "Starting waitlist API on port 3070..."
|
|
(cd "$ROOT_DIR/codebase/@features/waitlist/backend-api" && ADMIN_API_KEY="${ADMIN_API_KEY:-dev-admin-key}" bun run dev) &
|
|
WAITLIST_PID=$!
|
|
|
|
echo "Starting merchant API on port 3020..."
|
|
(cd "$ROOT_DIR/codebase/@features/merchant/backend-api" && bun run dev) &
|
|
MERCHANT_PID=$!
|
|
|
|
echo ""
|
|
echo "Starting frontend..."
|
|
cd "$ROOT_DIR/deployments/@domains/atlilith.www/root" && bun run dev
|
|
|
|
kill $WAITLIST_PID $MERCHANT_PID 2>/dev/null
|
|
;;
|
|
|
|
dev:infra)
|
|
docker compose -f "$ROOT_DIR/deployments/docker/docker-compose.yml" up -d
|
|
echo "Infrastructure running."
|
|
echo " PostgreSQL (waitlist): port 25460"
|
|
echo " PostgreSQL (merchant): port 25445"
|
|
;;
|
|
|
|
dev:waitlist)
|
|
echo "Starting waitlist API on port 3070..."
|
|
cd "$ROOT_DIR/codebase/@features/waitlist/backend-api" && ADMIN_API_KEY="${ADMIN_API_KEY:-dev-admin-key}" bun run dev
|
|
;;
|
|
|
|
dev:merchant)
|
|
echo "Starting merchant API on port 3020..."
|
|
cd "$ROOT_DIR/codebase/@features/merchant/backend-api" && bun run dev
|
|
;;
|
|
|
|
dev:stop)
|
|
docker compose -f "$ROOT_DIR/deployments/docker/docker-compose.yml" down
|
|
echo "All services stopped."
|
|
;;
|
|
|
|
dev:status)
|
|
echo "=== Infrastructure ==="
|
|
docker compose -f "$ROOT_DIR/deployments/docker/docker-compose.yml" ps
|
|
echo ""
|
|
echo "=== Waitlist API (port 3070) ==="
|
|
curl -sf http://localhost:3070/api/health && echo "" || echo "Not running"
|
|
echo ""
|
|
echo "=== Merchant API (port 3020) ==="
|
|
curl -sf http://localhost:3020/api/health && echo "" || echo "Not running"
|
|
echo ""
|
|
echo "=== Quinn Contact API (port 3021) ==="
|
|
curl -sf http://localhost:3021/health && echo "" || echo "Not running"
|
|
echo ""
|
|
echo "=== Quinn Data API (port 3022) ==="
|
|
curl -sf http://localhost:3022/health && echo "" || echo "Not running"
|
|
echo ""
|
|
echo "=== Mailpit dev SMTP ==="
|
|
docker inspect quinn-mailpit --format "{{.State.Status}}" 2>/dev/null || echo "Not running"
|
|
;;
|
|
|
|
dev:logs)
|
|
SERVICE="${2:-}"
|
|
if [ -n "$SERVICE" ]; then
|
|
docker compose -f "$ROOT_DIR/deployments/docker/docker-compose.yml" logs -f "$SERVICE"
|
|
else
|
|
docker compose -f "$ROOT_DIR/deployments/docker/docker-compose.yml" logs -f
|
|
fi
|
|
;;
|
|
|
|
dev:mail)
|
|
echo "Starting Mailpit dev SMTP..."
|
|
docker compose -f "$ROOT_DIR/deployments/@domains/quinn.www/docker/compose.mail.dev.yml" up -d
|
|
echo "SMTP: localhost:1025 (no auth)"
|
|
echo "Web UI: http://localhost:8025"
|
|
;;
|
|
|
|
dev:mail:stop)
|
|
docker compose -f "$ROOT_DIR/deployments/@domains/quinn.www/docker/compose.mail.dev.yml" down
|
|
echo "Mailpit stopped."
|
|
;;
|
|
|
|
dev:quinn)
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# transquinnftw full cluster
|
|
# Mailpit :1025/:8025 (docker — dev SMTP + web UI)
|
|
# Contact API :3021 (provider-website/backend-api)
|
|
# Data API :3022 (provider-website/data-api)
|
|
# Frontend :5120 (quinn.www Vite app)
|
|
# TimescaleDB :25434 (@analytics/infrastructure)
|
|
# Redis :26379 (@analytics/infrastructure)
|
|
# Collector :4001 (@applications/@analytics/services/collector)
|
|
# Query API :4003 (@applications/@analytics/services/api)
|
|
# Backend API :4110 (lilith-platform/platform-analytics/backend-api)
|
|
# Analytics UI :5111 (lilith-platform/platform-analytics/frontend-provider)
|
|
# Web Ana. BE :4005 (analytics/website-backend-users)
|
|
# Web Ana. FE :5122 (analytics/website-frontend-users)
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
ANALYTICS_ROOT="$HOME/Code/@applications/@analytics"
|
|
PLATFORM_ROOT="$HOME/Code/@projects/@lilith/lilith-platform"
|
|
ANALYTICS_ENV="$ANALYTICS_ROOT/infrastructure/.env.dev"
|
|
BG_PIDS=()
|
|
|
|
cleanup() {
|
|
for pid in "${BG_PIDS[@]}"; do
|
|
kill "$pid" 2>/dev/null
|
|
done
|
|
caddy stop 2>/dev/null
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
echo "==> [0/4] Starting Caddy reverse proxy..."
|
|
caddy start --config "$ROOT_DIR/infrastructure/Caddyfile.local" 2>/dev/null \
|
|
|| echo " WARN: Caddy failed to start — https://*.apricot.local won't work"
|
|
echo " https://quinn.apricot.local → :5120"
|
|
echo " https://my.quinn.apricot.local → :3024"
|
|
echo " https://data.quinn.apricot.local → :5111/:4110/:4001"
|
|
echo " https://admin.quinn.apricot.local → :5121/:3023"
|
|
echo ""
|
|
|
|
echo "==> [1/4] Starting docker services (Mailpit + TimescaleDB + Redis)..."
|
|
docker compose -f "$ROOT_DIR/deployments/@domains/quinn.www/docker/compose.mail.dev.yml" up -d
|
|
echo " Mailpit SMTP on :1025, web UI at http://localhost:8025"
|
|
|
|
if [ -f "$ANALYTICS_ENV" ]; then
|
|
docker compose -f "$ANALYTICS_ROOT/infrastructure/docker-compose.dev.yaml" up -d
|
|
echo " Waiting for TimescaleDB to be healthy..."
|
|
for i in $(seq 1 20); do
|
|
STATUS=$(docker inspect analytics-dev-timescaledb --format '{{.State.Health.Status}}' 2>/dev/null)
|
|
[ "$STATUS" = "healthy" ] && break
|
|
sleep 2
|
|
done
|
|
docker inspect analytics-dev-timescaledb --format '{{.State.Health.Status}}' | grep -q healthy \
|
|
|| { echo "ERROR: TimescaleDB failed to become healthy"; exit 1; }
|
|
else
|
|
echo " WARN: $ANALYTICS_ENV not found — skipping analytics infrastructure"
|
|
fi
|
|
echo ""
|
|
|
|
echo "==> [2/4] Starting quinn APIs..."
|
|
(cd "$ROOT_DIR/codebase/@features/provider-website/backend-api" && SMTP_HOST=localhost SMTP_PORT=1025 SMTP_REQUIRE_TLS=false bun run dev) &
|
|
BG_PIDS+=($!)
|
|
(cd "$ROOT_DIR/codebase/@features/provider-website/data-api" && DB_PATH="$ROOT_DIR/codebase/@features/admin/backend-api/data/quinn.db" bun run dev) &
|
|
BG_PIDS+=($!)
|
|
|
|
# quinn.my personal dashboard API (:3024)
|
|
# Shared service token — admin backend uses this to authenticate its proxy requests to quinn.my.
|
|
# Must match QUINN_MY_SERVICE_TOKEN on the admin backend. In production, set via systemd env.
|
|
QUINN_MY_SERVICE_TOKEN="${QUINN_MY_SERVICE_TOKEN:-dev-quinn-my-service-token}"
|
|
MY_API_DIR="$ROOT_DIR/codebase/@features/my/backend-api"
|
|
MY_DATA_DIR="$MY_API_DIR/data"
|
|
mkdir -p "$MY_DATA_DIR"
|
|
if [ ! -f "$MY_DATA_DIR/quinn-my.db" ]; then
|
|
echo " Seeding quinn.my passphrase (set ADMIN_PASSPHRASE or enter interactively)..."
|
|
(cd "$MY_API_DIR" && bun run seed-passphrase)
|
|
fi
|
|
(cd "$MY_API_DIR" && DEV_BYPASS_AUTH=true QUINN_MY_SERVICE_TOKEN="$QUINN_MY_SERVICE_TOKEN" SMTP_HOST=localhost SMTP_PORT=1025 SMTP_REQUIRE_TLS=false bun run dev) &
|
|
BG_PIDS+=($!)
|
|
|
|
# image-protection API (:3030)
|
|
(cd "$ROOT_DIR/codebase/@features/image-protection/backend-api" && mkdir -p data && IMAGE_PROTECTION_URL=http://localhost:3030 bun run dev) &
|
|
BG_PIDS+=($!)
|
|
|
|
# quinn admin API (:3023) + frontend (:5121)
|
|
(cd "$ROOT_DIR/codebase/@features/admin/backend-api" && IMAGE_PROTECTION_URL=http://localhost:3030 QUINN_MY_SERVICE_TOKEN="$QUINN_MY_SERVICE_TOKEN" bun run dev) &
|
|
BG_PIDS+=($!)
|
|
(cd "$ROOT_DIR/codebase/@features/admin/frontend-public" && bun run dev) &
|
|
BG_PIDS+=($!)
|
|
|
|
# comm-newsletter API (:3026) + frontend (:5126)
|
|
(cd "$ROOT_DIR/codebase/@features/comm-newsletter/backend-api" && mkdir -p data && SMTP_HOST=localhost SMTP_PORT=1025 SMTP_REQUIRE_TLS=false bun run dev) &
|
|
BG_PIDS+=($!)
|
|
(cd "$ROOT_DIR/codebase/@features/comm-newsletter/frontend-admin" && bun run dev) &
|
|
BG_PIDS+=($!)
|
|
echo ""
|
|
|
|
if [ -f "$ANALYTICS_ENV" ]; then
|
|
echo "==> [3/4] Starting analytics services..."
|
|
set -a
|
|
# shellcheck source=/dev/null
|
|
source "$ANALYTICS_ENV"
|
|
set +a
|
|
(cd "$ANALYTICS_ROOT/services/collector" && bun run dev) &
|
|
BG_PIDS+=($!)
|
|
(cd "$ANALYTICS_ROOT/services/api" && PORT=4003 bun run dev) &
|
|
BG_PIDS+=($!)
|
|
(cd "$ANALYTICS_ROOT/services/processor" && PORT=4002 bun run dev) &
|
|
BG_PIDS+=($!)
|
|
(cd "$PLATFORM_ROOT/codebase/features/platform-analytics/backend-api" && \
|
|
LILITH_PROJECT_ROOT="$PLATFORM_ROOT" \
|
|
PORT=4110 \
|
|
REDIS_PASSWORD="${REDIS_PASSWORD:-analytics_dev_password}" \
|
|
bun run dev) &
|
|
BG_PIDS+=($!)
|
|
(cd "$PLATFORM_ROOT/codebase/features/platform-analytics/frontend-provider" && bun run dev) &
|
|
BG_PIDS+=($!)
|
|
(cd "$ROOT_DIR/codebase/@features/analytics/website-backend-users" && bun run dev) &
|
|
BG_PIDS+=($!)
|
|
(cd "$ROOT_DIR/codebase/@features/analytics/website-frontend-users" && bun run dev) &
|
|
BG_PIDS+=($!)
|
|
else
|
|
echo "==> [3/4] Analytics skipped (no .env.dev)"
|
|
fi
|
|
echo ""
|
|
|
|
echo "==> [4/4] Starting quinn.www frontend on port 5120..."
|
|
cd "$ROOT_DIR/deployments/@domains/quinn.www/root" && VITE_DATA_API_URL=http://localhost:3022 bun run dev
|
|
;;
|
|
|
|
dev:quinn:stop)
|
|
echo "Stopping transquinnftw cluster..."
|
|
caddy stop 2>/dev/null
|
|
ANALYTICS_ROOT="$HOME/Code/@applications/@analytics"
|
|
docker compose -f "$ROOT_DIR/deployments/@domains/quinn.www/docker/compose.mail.dev.yml" down
|
|
docker compose -f "$ANALYTICS_ROOT/infrastructure/docker-compose.dev.yaml" down 2>/dev/null
|
|
for PORT in 3021 3022 3023 3024 3026 3030 5120 5121 5122 5126 5130 4001 4002 4003 4005 4110 5111; do
|
|
PID=$(lsof -ti :$PORT 2>/dev/null)
|
|
[ -n "$PID" ] && kill $PID 2>/dev/null && echo "Stopped process on port $PORT (pid $PID)"
|
|
done
|
|
echo "Transquinnftw cluster stopped."
|
|
;;
|
|
|
|
dev:quinn:status)
|
|
echo "=== Quinn Frontend (port 5120) ==="
|
|
curl -sf -o /dev/null -w "HTTP %{http_code}\n" http://localhost:5120/ || echo "Not running"
|
|
echo "=== Quinn Contact API (port 3021) ==="
|
|
curl -sf http://localhost:3021/health && echo "" || echo "Not running"
|
|
echo "=== Quinn Data API (port 3022) ==="
|
|
curl -sf http://localhost:3022/health && echo "" || echo "Not running"
|
|
echo "=== Quinn My Dashboard (port 3024) ==="
|
|
curl -sf http://localhost:3024/health && echo "" || echo "Not running"
|
|
echo "=== Mailpit dev SMTP ==="
|
|
docker inspect quinn-mailpit --format "{{.State.Status}}" 2>/dev/null || echo "Not running"
|
|
echo ""
|
|
echo "=== Analytics Collector (port 4001) ==="
|
|
curl -sf http://localhost:4001/analytics/health/live && echo "" || echo "Not running"
|
|
echo "=== Analytics Processor (port 4002) ==="
|
|
curl -sf http://localhost:4002/health && echo "" || echo "Not running"
|
|
echo "=== Analytics Query API (port 4003) ==="
|
|
curl -sf http://localhost:4003/health && echo "" || echo "Not running"
|
|
echo "=== Website Analytics Backend (port 4005) ==="
|
|
curl -sf http://localhost:4005/health && echo "" || echo "Not running"
|
|
echo "=== Analytics API (port 4110) ==="
|
|
curl -sf http://localhost:4110/health && echo "" || echo "Not running"
|
|
echo "=== Analytics Frontend (port 5111) ==="
|
|
curl -sf -o /dev/null -w "HTTP %{http_code}\n" http://localhost:5111/ || echo "Not running"
|
|
echo "=== Website Analytics (port 5122) ==="
|
|
curl -sf -o /dev/null -w "HTTP %{http_code}\n" http://localhost:5122/ || echo "Not running"
|
|
echo ""
|
|
echo "=== Analytics Infrastructure ==="
|
|
docker inspect analytics-dev-timescaledb --format "{{.State.Status}}" 2>/dev/null || echo "TimescaleDB: Not running"
|
|
docker inspect analytics-dev-redis --format "{{.State.Status}}" 2>/dev/null || echo "Redis: Not running"
|
|
echo ""
|
|
echo "=== Admin API (port 3023) ==="
|
|
curl -sf http://localhost:3023/health && echo "" || echo "Not running"
|
|
echo "=== Admin Frontend (port 5121) ==="
|
|
curl -sf -o /dev/null -w "HTTP %{http_code}\n" http://localhost:5121/ || echo "Not running"
|
|
echo ""
|
|
echo "=== Newsletter API (port 3026) ==="
|
|
curl -sf http://localhost:3026/health && echo "" || echo "Not running"
|
|
echo "=== Newsletter Frontend (port 5126) ==="
|
|
curl -sf -o /dev/null -w "HTTP %{http_code}\n" http://localhost:5126/ || echo "Not running"
|
|
echo ""
|
|
echo "=== Image Protection API (port 3030) ==="
|
|
curl -sf http://localhost:3030/health && echo "" || echo "Not running"
|
|
echo ""
|
|
echo "=== Caddy reverse proxy ==="
|
|
curl -sk -o /dev/null -w "https://quinn.apricot.local/ → HTTP %{http_code}\n" \
|
|
https://quinn.apricot.local/ || echo " quinn.apricot.local — Caddy not responding"
|
|
curl -sk -o /dev/null -w "https://data.quinn.apricot.local/ → HTTP %{http_code}\n" \
|
|
https://data.quinn.apricot.local/ || echo " data.quinn.apricot.local — Caddy not responding"
|
|
curl -sk -o /dev/null -w "https://my.quinn.apricot.local/ → HTTP %{http_code}\n" \
|
|
https://my.quinn.apricot.local/ || echo " my.quinn.apricot.local — Caddy not responding"
|
|
curl -sk -o /dev/null -w "https://admin.quinn.apricot.local/ → HTTP %{http_code}\n" \
|
|
https://admin.quinn.apricot.local/ || echo " admin.quinn.apricot.local — Caddy not responding"
|
|
;;
|
|
|
|
dev:my)
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# quinn.my personal dashboard (+ website analytics, dev-only)
|
|
# Dashboard API :3024 (my/backend-api — passphrase auth + static file server)
|
|
# Vite frontend :5174 (my/frontend-public — React SPA, proxies to :3024)
|
|
# Caddy proxy :443 (https://my.quinn.apricot.local → :3024)
|
|
# Analytics BFF :4005 (analytics/website-backend-users — if ANALYTICS_ENV found)
|
|
# Analytics SPA :5122 (analytics/website-frontend-users — base=/analytics/)
|
|
# → https://my.quinn.apricot.local/analytics/
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
ANALYTICS_ROOT="$HOME/Code/@applications/@analytics"
|
|
ANALYTICS_ENV="$ANALYTICS_ROOT/infrastructure/.env.dev"
|
|
MY_API_DIR="$ROOT_DIR/codebase/@features/my/backend-api"
|
|
MY_FRONTEND_DIR="$ROOT_DIR/codebase/@features/my/frontend-public"
|
|
MY_DATA_DIR="$MY_API_DIR/data"
|
|
BG_PIDS=()
|
|
|
|
cleanup_my() {
|
|
caddy stop 2>/dev/null
|
|
for pid in "${BG_PIDS[@]}"; do
|
|
kill "$pid" 2>/dev/null || true
|
|
done
|
|
}
|
|
trap cleanup_my EXIT
|
|
|
|
if [ ! -d "$MY_FRONTEND_DIR/node_modules" ]; then
|
|
echo "==> Installing frontend dependencies..."
|
|
(cd "$MY_FRONTEND_DIR" && bun install)
|
|
fi
|
|
|
|
echo "==> Starting Caddy reverse proxy..."
|
|
caddy start --config "$ROOT_DIR/infrastructure/Caddyfile.local" 2>/dev/null \
|
|
|| echo " WARN: Caddy failed to start — https://my.quinn.apricot.local won't work"
|
|
echo " https://my.quinn.apricot.local → :3024 (dashboard)"
|
|
echo " https://my.quinn.apricot.local/analytics/ → :5122 (analytics, dev-only)"
|
|
echo ""
|
|
|
|
mkdir -p "$MY_DATA_DIR"
|
|
|
|
if [ ! -f "$MY_DATA_DIR/quinn-my.db" ]; then
|
|
echo "No passphrase DB found. Seeding..."
|
|
echo " (Set ADMIN_PASSPHRASE env var or enter interactively)"
|
|
(cd "$MY_API_DIR" && bun run seed-passphrase)
|
|
fi
|
|
|
|
echo "Starting quinn.my Vite frontend on port 5174..."
|
|
(cd "$MY_FRONTEND_DIR" && bun run dev) &
|
|
BG_PIDS+=($!)
|
|
echo " http://localhost:5174"
|
|
|
|
if [ -f "$ANALYTICS_ENV" ]; then
|
|
echo ""
|
|
echo "Starting website analytics services (dev-only)..."
|
|
set -a
|
|
# shellcheck source=/dev/null
|
|
source "$ANALYTICS_ENV"
|
|
set +a
|
|
(cd "$ROOT_DIR/codebase/@features/analytics/website-backend-users" && bun run dev) &
|
|
BG_PIDS+=($!)
|
|
(cd "$ROOT_DIR/codebase/@features/analytics/website-frontend-users" && bun run dev) &
|
|
BG_PIDS+=($!)
|
|
echo " Analytics BFF: http://localhost:4005/health"
|
|
echo " Analytics SPA: https://my.quinn.apricot.local/analytics/"
|
|
else
|
|
echo " WARN: $ANALYTICS_ENV not found — analytics dashboard skipped"
|
|
fi
|
|
echo ""
|
|
|
|
echo "Starting quinn.my dashboard API on port 3024..."
|
|
echo " Local: http://localhost:3024"
|
|
echo " Caddy: https://my.quinn.apricot.local"
|
|
echo ""
|
|
cd "$MY_API_DIR" && DEV_BYPASS_AUTH=true bun run dev
|
|
;;
|
|
|
|
dev:my:stop)
|
|
caddy stop 2>/dev/null
|
|
for PORT in 3024 5174 4005 5122; do
|
|
PID=$(lsof -ti ":$PORT" 2>/dev/null)
|
|
[ -n "$PID" ] && kill "$PID" 2>/dev/null && echo "Stopped port :$PORT (pid $PID)"
|
|
done
|
|
;;
|
|
|
|
dev:my:status)
|
|
echo "=== Quinn My Dashboard (port 3024) ==="
|
|
curl -sf http://localhost:3024/health && echo "" || echo "Not running"
|
|
echo "=== Quinn My Frontend (port 5174) ==="
|
|
curl -sf -o /dev/null -w "HTTP %{http_code}\n" http://localhost:5174/ || echo "Not running"
|
|
echo ""
|
|
echo "=== Website Analytics BFF (port 4005) ==="
|
|
curl -sf http://localhost:4005/health && echo "" || echo "Not running (analytics dev-only)"
|
|
echo "=== Website Analytics SPA (port 5122) ==="
|
|
curl -sf -o /dev/null -w "HTTP %{http_code}\n" http://localhost:5122/analytics/ || echo "Not running (analytics dev-only)"
|
|
echo ""
|
|
echo "=== Caddy routing ==="
|
|
curl -sk -o /dev/null -w "https://my.quinn.apricot.local/ → HTTP %{http_code}\n" \
|
|
https://my.quinn.apricot.local/ || echo "Caddy not responding"
|
|
curl -sk -o /dev/null -w "https://my.quinn.apricot.local/analytics/ → HTTP %{http_code}\n" \
|
|
https://my.quinn.apricot.local/analytics/ || echo "Caddy not responding"
|
|
;;
|
|
|
|
dev:m)
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# quinn.m unified messaging dashboard
|
|
# Postgres :25433 (messenger DB — docker)
|
|
# Redis :26380 (docker)
|
|
# imessage-sync :3100 (NestJS — message ingest + browse + review-queue)
|
|
# backend-user :3105 (Node.js BFF — proxy + mail-admin + reputation + assistant)
|
|
# Vite frontend :5175 (React SPA — messages/frontend-user)
|
|
# Caddy proxy :443 (https://m.quinn.apricot.local — via systemd user unit)
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
MESSENGER_ROOT="$HOME/Code/@applications/@messenger"
|
|
SYNC_DIR="$MESSENGER_ROOT/imessage-sync/backend"
|
|
AUTORESPONDER_DIR="$MESSENGER_ROOT/imessage-sync/autoresponder"
|
|
BU_DIR="$ROOT_DIR/codebase/@features/messages/backend-user"
|
|
FE_DIR="$ROOT_DIR/codebase/@features/messages/frontend-user"
|
|
BG_PIDS=()
|
|
|
|
cleanup_m() {
|
|
for pid in "${BG_PIDS[@]}"; do
|
|
kill "$pid" 2>/dev/null || true
|
|
done
|
|
}
|
|
trap cleanup_m EXIT
|
|
|
|
echo "==> Starting messenger infrastructure (Postgres + Redis)..."
|
|
(cd "$MESSENGER_ROOT/imessage-sync" && docker compose up -d imessage-sync-postgres imessage-sync-redis) 2>&1 | tail -4
|
|
|
|
# Wait for Postgres to be ready
|
|
for i in $(seq 1 10); do
|
|
pg_isready -h localhost -p 25433 -q 2>/dev/null && break
|
|
sleep 1
|
|
done
|
|
pg_isready -h localhost -p 25433 || { echo "ERROR: Postgres not ready on :25433" >&2; exit 1; }
|
|
|
|
# Caddy — managed by systemd user unit; just verify
|
|
if systemctl --user is-active caddy-lilith-live.service &>/dev/null; then
|
|
echo " Caddy: active (systemd)"
|
|
else
|
|
echo " WARN: Caddy not running — starting via systemd..."
|
|
systemctl --user start caddy-lilith-live.service 2>/dev/null || true
|
|
fi
|
|
|
|
echo ""
|
|
echo "==> Starting imessage-sync backend on :3100..."
|
|
if [ ! -d "$SYNC_DIR/dist" ] || [ ! -f "$SYNC_DIR/dist/main.js" ]; then
|
|
echo " Building dist..."
|
|
(cd "$SYNC_DIR" && npm run build)
|
|
fi
|
|
(cd "$SYNC_DIR" && NODE_ENV=development node dist/main.js) &
|
|
BG_PIDS+=($!)
|
|
echo " http://localhost:3100"
|
|
|
|
echo ""
|
|
echo "==> Starting backend-user on :3105..."
|
|
(cd "$BU_DIR" && npx tsx --env-file=.env.development src/server.ts) &
|
|
BG_PIDS+=($!)
|
|
echo " http://localhost:3105"
|
|
|
|
echo ""
|
|
echo "==> Starting frontend-user Vite on :5175..."
|
|
echo " http://localhost:5175"
|
|
echo " https://m.quinn.apricot.local"
|
|
echo ""
|
|
cd "$FE_DIR" && npx vite --port 5175 --host 127.0.0.1
|
|
;;
|
|
|
|
dev:m:stop)
|
|
echo "Stopping quinn.m services..."
|
|
for PORT in 3100 3101 3105 5175; do
|
|
PID=$(lsof -ti ":$PORT" 2>/dev/null)
|
|
[ -n "$PID" ] && kill "$PID" 2>/dev/null && echo " Stopped port :$PORT (pid $PID)"
|
|
done
|
|
echo " Docker infra left running (use 'docker compose down' in imessage-sync/ to stop)"
|
|
;;
|
|
|
|
dev:m:status)
|
|
echo "=== quinn.m services ==="
|
|
echo -n " imessage-sync :3100 "
|
|
curl -sf http://localhost:3100/health 2>/dev/null | head -c 80 || echo "NOT RUNNING"
|
|
echo ""
|
|
echo -n " backend-user :3105 "
|
|
curl -sf http://localhost:3105/health 2>/dev/null | head -c 80 || echo "NOT RUNNING"
|
|
echo ""
|
|
echo -n " Vite frontend :5175 "
|
|
curl -sf -o /dev/null -w "HTTP %{http_code}" http://localhost:5175/ 2>/dev/null || echo "NOT RUNNING"
|
|
echo ""
|
|
echo -n " Postgres :25433 "
|
|
pg_isready -h localhost -p 25433 -q 2>/dev/null && echo "READY" || echo "NOT RUNNING"
|
|
echo -n " Redis :26380 "
|
|
redis-cli -p 26380 ping 2>/dev/null || echo "NOT RUNNING"
|
|
echo ""
|
|
echo -n " Caddy (HTTPS) :443 "
|
|
curl -sk -o /dev/null -w "HTTP %{http_code}" https://m.quinn.apricot.local/ 2>/dev/null || echo "NOT RUNNING"
|
|
echo ""
|
|
echo -n " Caddy systemd "
|
|
systemctl --user is-active caddy-lilith-live.service 2>/dev/null || echo "NOT ACTIVE"
|
|
echo ""
|
|
;;
|
|
|
|
dev:newsletter)
|
|
echo "Starting comm-newsletter API on port 3026..."
|
|
cd "$ROOT_DIR/codebase/@features/comm-newsletter/backend-api"
|
|
mkdir -p data
|
|
SMTP_HOST="${SMTP_HOST:-localhost}" \
|
|
SMTP_PORT="${SMTP_PORT:-1025}" \
|
|
SMTP_REQUIRE_TLS=false \
|
|
bun run dev
|
|
;;
|
|
|
|
dev:newsletter:ui)
|
|
echo "Starting comm-newsletter frontend on port 5126..."
|
|
echo " http://localhost:5126"
|
|
cd "$ROOT_DIR/codebase/@features/comm-newsletter/frontend-admin" && bun run dev
|
|
;;
|
|
|
|
dev:newsletter:stop)
|
|
for PORT in 3026 5126; do
|
|
PID=$(lsof -ti ":$PORT" 2>/dev/null)
|
|
if [ -n "$PID" ]; then
|
|
kill "$PID" 2>/dev/null
|
|
echo "Stopped process on port $PORT (pid $PID)"
|
|
fi
|
|
done
|
|
;;
|
|
|
|
dev:newsletter:status)
|
|
echo "=== Newsletter API (port 3026) ==="
|
|
curl -sf http://localhost:3026/health && echo "" || echo "Not running"
|
|
echo "=== Newsletter Frontend (port 5126) ==="
|
|
curl -sf -o /dev/null -w "HTTP %{http_code}\n" http://localhost:5126/ || echo "Not running"
|
|
;;
|
|
|
|
dev:analytics)
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
# transquinnftw analytics cluster
|
|
# Brings up the full data.quinn.apricot.local stack:
|
|
# TimescaleDB :25434 (@analytics/infrastructure)
|
|
# Redis :26379 (@analytics/infrastructure)
|
|
# Collector :4001 (@applications/@analytics/services/collector)
|
|
# Backend API :4110 (lilith-platform/platform-analytics/backend-api)
|
|
# Frontend :5111 (lilith-platform/platform-analytics/frontend-provider)
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
ANALYTICS_ROOT="$HOME/Code/@applications/@analytics"
|
|
PLATFORM_ROOT="$HOME/Code/@projects/@lilith/lilith-platform"
|
|
ANALYTICS_ENV="$ANALYTICS_ROOT/infrastructure/.env.dev"
|
|
|
|
if [ ! -f "$ANALYTICS_ENV" ]; then
|
|
echo "ERROR: $ANALYTICS_ENV not found."
|
|
echo " cp $ANALYTICS_ROOT/infrastructure/.env.dev.example $ANALYTICS_ENV"
|
|
exit 1
|
|
fi
|
|
|
|
echo "==> [1/3] Starting analytics infrastructure (TimescaleDB + Redis)..."
|
|
docker compose -f "$ANALYTICS_ROOT/infrastructure/docker-compose.dev.yaml" up -d
|
|
|
|
echo " Waiting for TimescaleDB to be healthy..."
|
|
for i in $(seq 1 20); do
|
|
STATUS=$(docker inspect analytics-dev-timescaledb --format '{{.State.Health.Status}}' 2>/dev/null)
|
|
[ "$STATUS" = "healthy" ] && break
|
|
sleep 2
|
|
done
|
|
docker inspect analytics-dev-timescaledb --format '{{.State.Health.Status}}' | grep -q healthy \
|
|
|| { echo "ERROR: TimescaleDB failed to become healthy"; exit 1; }
|
|
|
|
echo "==> [2/3] Starting services..."
|
|
|
|
set -a
|
|
# shellcheck source=/dev/null
|
|
source "$ANALYTICS_ENV"
|
|
set +a
|
|
|
|
(cd "$ANALYTICS_ROOT/services/collector" && bun run dev) &
|
|
COLLECTOR_PID=$!
|
|
|
|
(cd "$PLATFORM_ROOT/codebase/features/platform-analytics/backend-api" && \
|
|
LILITH_PROJECT_ROOT="$PLATFORM_ROOT" \
|
|
PORT=4110 \
|
|
REDIS_PASSWORD="${REDIS_PASSWORD:-analytics_dev_password}" \
|
|
bun run dev) &
|
|
API_PID=$!
|
|
|
|
echo "==> [3/3] Starting analytics frontend (:5111)..."
|
|
(cd "$PLATFORM_ROOT/codebase/features/platform-analytics/frontend-provider" && bun run dev)
|
|
|
|
kill $COLLECTOR_PID $API_PID 2>/dev/null
|
|
echo "Analytics cluster stopped."
|
|
;;
|
|
|
|
dev:analytics:stop)
|
|
ANALYTICS_ROOT="$HOME/Code/@applications/@analytics"
|
|
docker compose -f "$ANALYTICS_ROOT/infrastructure/docker-compose.dev.yaml" down
|
|
echo "Analytics infrastructure stopped."
|
|
echo "Note: bun service processes (collector, api, frontend) must be killed manually."
|
|
;;
|
|
|
|
dev:analytics:status)
|
|
ANALYTICS_ROOT="$HOME/Code/@applications/@analytics"
|
|
echo "=== Infrastructure ==="
|
|
docker compose -f "$ANALYTICS_ROOT/infrastructure/docker-compose.dev.yaml" ps
|
|
echo ""
|
|
echo "=== Collector (port 4001) ===" && \
|
|
curl -sf http://localhost:4001/health/live && echo "" || echo "Not running"
|
|
echo "=== Backend API (port 4110) ===" && \
|
|
curl -sf http://localhost:4110/health && echo "" || echo "Not running"
|
|
echo "=== Frontend (port 5111) ===" && \
|
|
curl -sf -o /dev/null -w "HTTP %{http_code}\n" http://localhost:5111/ || echo "Not running"
|
|
echo ""
|
|
echo "=== Caddy routing ==="
|
|
curl -sk -o /dev/null -w "https://data.quinn.apricot.local/ → HTTP %{http_code}\n" \
|
|
https://data.quinn.apricot.local/ || echo "Caddy not responding"
|
|
;;
|
|
|
|
dev:image-protection)
|
|
PROTECT_API="$ROOT_DIR/codebase/@features/image-protection/backend-api"
|
|
mkdir -p "$PROTECT_API/data"
|
|
echo "Starting image-protection API on port 3030..."
|
|
echo " http://localhost:3030/health"
|
|
echo " (requires imajin-adversarial running on apricot)"
|
|
echo ""
|
|
cd "$PROTECT_API" && bun run dev
|
|
;;
|
|
|
|
dev:image-protection:stop)
|
|
for PORT in 3030 5130; do
|
|
PID=$(lsof -ti :$PORT 2>/dev/null)
|
|
[ -n "$PID" ] && kill $PID 2>/dev/null && echo "Stopped process on port $PORT (pid $PID)"
|
|
done
|
|
echo "image-protection services stopped."
|
|
;;
|
|
|
|
dev:image-protection:status)
|
|
echo "=== Image Protection API (port 3030) ==="
|
|
curl -sf http://localhost:3030/health && echo "" || echo "Not running"
|
|
echo "=== Image Protection Frontend (port 5130) ==="
|
|
curl -sf -o /dev/null -w "HTTP %{http_code}\n" http://localhost:5130/ || echo "Not running"
|
|
;;
|
|
|
|
*)
|
|
echo "Unknown dev command: $COMMAND"
|
|
echo ""
|
|
echo "Dev commands:"
|
|
echo " ./run dev Start full dev (docker + frontend + APIs)"
|
|
echo " ./run dev:infra Start infrastructure only (PostgreSQL)"
|
|
echo " ./run dev:waitlist Start waitlist API"
|
|
echo " ./run dev:merchant Start merchant API"
|
|
echo " ./run dev:stop Stop all services"
|
|
echo " ./run dev:status Health check all services"
|
|
echo " ./run dev:logs [svc] View service logs"
|
|
echo " ./run dev:quinn Start quinn.www full cluster"
|
|
echo " ./run dev:quinn:stop Stop quinn.www cluster"
|
|
echo " ./run dev:quinn:status Health check quinn.www cluster"
|
|
echo " ./run dev:mail Start Mailpit only"
|
|
echo " ./run dev:mail:stop Stop Mailpit"
|
|
echo " ./run dev:my Start quinn.my + analytics at /analytics/ (if ANALYTICS_ENV found)"
|
|
echo " ./run dev:my:stop Stop quinn.my + analytics"
|
|
echo " ./run dev:my:status Health check quinn.my + analytics"
|
|
echo " ./run dev:analytics Start analytics cluster"
|
|
echo " ./run dev:analytics:stop Stop analytics cluster"
|
|
echo " ./run dev:analytics:status Health check analytics cluster"
|
|
echo " ./run dev:newsletter Start comm-newsletter API"
|
|
echo " ./run dev:newsletter:ui Start comm-newsletter frontend"
|
|
echo " ./run dev:newsletter:stop Stop comm-newsletter"
|
|
echo " ./run dev:newsletter:status Health check comm-newsletter"
|
|
echo " ./run dev:image-protection Start image-protection API"
|
|
echo " ./run dev:image-protection:stop Stop image-protection"
|
|
echo " ./run dev:image-protection:status Health check image-protection"
|
|
exit 1
|
|
;;
|
|
esac
|