#!/usr/bin/env bash set -euo pipefail echo "[start-web] Starting web service..." echo "[start-web] Bun: $(bun --version || true)" cd /app export BUN_INSTALL_CACHE_DIR="${BUN_INSTALL_CACHE_DIR:-/tmp/bun-cache}" mkdir -p "$BUN_INSTALL_CACHE_DIR" DB_PATH="/app/data/db.sqlite" echo "[start-web] Using bun cache dir: $BUN_INSTALL_CACHE_DIR" echo "[start-web] Using APP_DIR=$(pwd)" echo "[start-web] NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL:-}" echo "[start-web] NEXT_PUBLIC_CONVEX_URL=${NEXT_PUBLIC_CONVEX_URL:-}" ensure_db_writable() { mkdir -p "$(dirname "$DB_PATH")" if [ ! -e "$DB_PATH" ]; then touch "$DB_PATH" || true chmod 660 "$DB_PATH" 2>/dev/null || true fi if ! touch "$DB_PATH" >/dev/null 2>&1; then echo "[start-web] ERRO: não foi possível escrever em $DB_PATH (verifique permissões do volume /app/data)" >&2 ls -ld /app/data "$DB_PATH" >/dev/null 2>&1 || true exit 1 fi } ensure_db_writable # Ensure system deps for native modules (best-effort, idempotent) if command -v apt-get >/dev/null 2>&1; then if [ "${SKIP_APT_BOOTSTRAP:-false}" = "true" ]; then echo "[start-web] SKIP_APT_BOOTSTRAP=true; skipping apt bootstrap" else # Ensure curl/gnupg for NodeSource setup if ! command -v curl >/dev/null 2>&1; then apt-get update -y || true apt-get install -y --no-install-recommends curl ca-certificates gnupg || true fi install_node() { local current_node_major="" if command -v node >/dev/null 2>&1; then current_node_major=$(node -v | sed -E 's/^v([0-9]+).*/\1/') if [ -n "$current_node_major" ] && [ "$current_node_major" -ge 20 ]; then return 0 fi fi echo "[start-web] installing Node.js 22.x via NodeSource" curl -fsSL https://deb.nodesource.com/setup_22.x | bash - || true apt-get update -y || true apt-get install -y --no-install-recommends nodejs || true } # Base toolchain for native modules apt-get update -y || true apt-get install -y --no-install-recommends build-essential python3 make pkg-config || true if ! command -v openssl >/dev/null 2>&1; then echo "[start-web] openssl not found; installing via apt-get (requires root)" apt-get update -y || true apt-get install -y --no-install-recommends openssl ca-certificates || true fi if ! command -v node >/dev/null 2>&1 && [ -x /usr/bin/nodejs ]; then ln -sf /usr/bin/nodejs /usr/bin/node || true fi install_node fi else echo "[start-web] apt-get unavailable; skipping system deps install" >&2 fi # Rebuild native better-sqlite3 bindings for the current Node version if command -v npm >/dev/null 2>&1; then check_better_sqlite3() { node - <<'EOF' const path = require("node:path") try { const pkgPath = require.resolve("better-sqlite3/package.json") const pkg = require(pkgPath) const binding = path.join(path.dirname(pkgPath), "build", "Release", "better_sqlite3.node") require("better-sqlite3") console.log(`[start-web] better-sqlite3 ok (v${pkg.version}) binding=${binding}`) process.exit(0) } catch (error) { console.error("[start-web] better-sqlite3 load failed:", error?.message || error) process.exit(1) } EOF } rebuild_and_repin_sqlite() { echo "[start-web] rebuilding better-sqlite3 para a runtime atual" npm rebuild better-sqlite3 --build-from-source >/dev/null 2>&1 || { echo "[start-web] rebuild falhou; continuando com bindings existentes" >&2 } node - <<'EOF' const fs = require("node:fs") const path = require("node:path") try { const pkgPath = require.resolve("better-sqlite3/package.json") const pkgDir = path.dirname(pkgPath) const pkg = require(pkgPath) const built = path.join(pkgDir, "build", "Release", "better_sqlite3.node") const store = path.join(process.cwd(), "node_modules", ".bun", `better-sqlite3@${pkg.version}`, "node_modules", "better-sqlite3", "build", "Release", "better_sqlite3.node") fs.mkdirSync(path.dirname(store), { recursive: true }) fs.copyFileSync(built, store) console.log(`[start-web] better-sqlite3 (v${pkg.version}) copiado para store bun: ${store}`) } catch (error) { console.error("[start-web] não foi possível copiar binding para .bun store:", error?.message || error) } EOF } if [ "${SKIP_SQLITE_REBUILD:-false}" = "true" ]; then echo "[start-web] SKIP_SQLITE_REBUILD=true; tentando usar bindings existentes" if ! check_better_sqlite3; then echo "[start-web] bindings inválidos; forçando rebuild mesmo com SKIP_SQLITE_REBUILD=true" rebuild_and_repin_sqlite check_better_sqlite3 || { echo "[start-web] ERRO: better-sqlite3 continua inválido após rebuild" >&2 exit 1 } fi else rebuild_and_repin_sqlite check_better_sqlite3 || { echo "[start-web] ERRO: better-sqlite3 inválido após rebuild" >&2 exit 1 } fi fi # Bun keeps its store in node_modules/.bun by default; ensure it exists and is writable mkdir -p node_modules/.bun >/dev/null 2>&1 || true # Prisma generate (idempotent) and apply DB migrations echo "[start-web] prisma generate (bun runtime)" bunx --bun prisma generate echo "[start-web] prisma migrate deploy (bun runtime)" bunx --bun prisma migrate deploy # Seed Better Auth users safely (ensure-only by default) if [ "${SKIP_AUTH_SEED:-false}" != "true" ]; then echo "[start-web] seeding Better Auth users (ensure-only)" bun run auth:seed || true else echo "[start-web] skipping auth seed (SKIP_AUTH_SEED=true)" fi echo "[start-web] launching Next.js" PORT=${PORT:-3000} NODE_MAJOR=$(command -v node >/dev/null 2>&1 && node -v | sed -E 's/^v([0-9]+).*/\1/' || echo "") if [ -z "$NODE_MAJOR" ] || [ "$NODE_MAJOR" -lt 20 ]; then echo "[start-web] Node.js 20+ not available; aborting" exit 1 fi exec node node_modules/next/dist/bin/next start --port "$PORT"