#!/usr/bin/env sh set -eu cd /workspace /bin/sh ./scripts/sync_userfront_locales.sh cd /workspace/userfront USERFRONT_INTERNAL_PORT="${USERFRONT_INTERNAL_PORT:-5000}" USERFRONT_FLUTTER_RUN_FLAGS="${USERFRONT_FLUTTER_RUN_FLAGS:---debug}" USERFRONT_BOOT_WARMUP_ATTEMPTS="${USERFRONT_BOOT_WARMUP_ATTEMPTS:-120}" USERFRONT_BOOT_WARMUP_INTERVAL_SECONDS="${USERFRONT_BOOT_WARMUP_INTERVAL_SECONDS:-0.5}" USERFRONT_BOOT_WARMUP_LOCALES="${USERFRONT_BOOT_WARMUP_LOCALES:-ko en}" USERFRONT_BOOT_WARMUP_VIEWPORTS="${USERFRONT_BOOT_WARMUP_VIEWPORTS:-mobile:390 desktop:1440}" USERFRONT_BOOT_BUILD_MARKER="${USERFRONT_BOOT_BUILD_MARKER:-build/.userfront-boot-build-start}" USERFRONT_BOOT_LOG="${USERFRONT_BOOT_LOG:-build/userfront-boot-flutter.log}" USERFRONT_BOOT_LOG_PIPE="${USERFRONT_BOOT_LOG_PIPE:-build/userfront-boot-flutter.pipe}" echo "[userfront-boot] removing stale build/web before flutter run" >&2 rm -rf build/web mkdir -p "$(dirname "$USERFRONT_BOOT_BUILD_MARKER")" : > "$USERFRONT_BOOT_BUILD_MARKER" warm_get() { path="$1" locale="$2" viewport="$3" width="${viewport#*:}" if [ "$width" = "$viewport" ]; then width="" fi wget -qO- \ --header="Accept-Language: $locale" \ --header="Viewport-Width: $width" \ "http://127.0.0.1:${USERFRONT_INTERNAL_PORT}${path}" >/dev/null 2>&1 } wait_for_userfront_build() { flutter_pid="$1" attempt=1 while [ "$attempt" -le "$USERFRONT_BOOT_WARMUP_ATTEMPTS" ]; do if [ -f "build/web/index.html" ] && [ "build/web/index.html" -nt "$USERFRONT_BOOT_BUILD_MARKER" ]; then return 0 fi if ! kill -0 "$flutter_pid" 2>/dev/null; then echo "[userfront-boot] warmup skipped because flutter exited before build/web/index.html was ready" >&2 return 1 fi attempt=$((attempt + 1)) sleep "$USERFRONT_BOOT_WARMUP_INTERVAL_SECONDS" done echo "[userfront-boot] warmup skipped after ${USERFRONT_BOOT_WARMUP_ATTEMPTS} build readiness attempts" >&2 return 1 } wait_for_userfront_serve_log() { flutter_pid="$1" attempt=1 while [ "$attempt" -le "$USERFRONT_BOOT_WARMUP_ATTEMPTS" ]; do if [ -f "$USERFRONT_BOOT_LOG" ] && grep -Fq "lib/main.dart is being served at" "$USERFRONT_BOOT_LOG"; then return 0 fi if ! kill -0 "$flutter_pid" 2>/dev/null; then echo "[userfront-boot] warmup skipped because flutter exited before serve log was ready" >&2 return 1 fi attempt=$((attempt + 1)) sleep "$USERFRONT_BOOT_WARMUP_INTERVAL_SECONDS" done echo "[userfront-boot] warmup skipped after ${USERFRONT_BOOT_WARMUP_ATTEMPTS} serve readiness attempts" >&2 return 1 } disable_userfront_dev_service_worker() { cat > build/web/flutter_service_worker.js <<'EOF' self.addEventListener("install", (event) => { self.skipWaiting(); }); self.addEventListener("activate", (event) => { event.waitUntil(self.registration.unregister()); }); EOF } warm_flutter_bootstrap_assets() { if [ ! -f build/web/flutter_bootstrap.js ]; then return 0 fi grep -Eo 'main\.dart\.[^"]+\.(js|mjs|wasm)' build/web/flutter_bootstrap.js \ | sort -u \ | while IFS= read -r asset; do [ -n "$asset" ] || continue wget -qO- "http://127.0.0.1:${USERFRONT_INTERNAL_PORT}/${asset}" >/dev/null 2>&1 || \ echo "[userfront-boot] warmup warning: failed to load /${asset}" >&2 done } warm_userfront_once() { flutter_pid="$1" attempt=1 if ! wait_for_userfront_serve_log "$flutter_pid"; then return 0 fi if ! wait_for_userfront_build "$flutter_pid"; then return 0 fi disable_userfront_dev_service_worker while [ "$attempt" -le "$USERFRONT_BOOT_WARMUP_ATTEMPTS" ]; do if wget -qO- "http://127.0.0.1:${USERFRONT_INTERNAL_PORT}/flutter_bootstrap.js" >/dev/null 2>&1; then break fi if ! kill -0 "$flutter_pid" 2>/dev/null; then echo "[userfront-boot] warmup skipped because flutter exited before readiness" >&2 return 0 fi attempt=$((attempt + 1)) sleep "$USERFRONT_BOOT_WARMUP_INTERVAL_SECONDS" done if [ "$attempt" -gt "$USERFRONT_BOOT_WARMUP_ATTEMPTS" ]; then echo "[userfront-boot] warmup skipped after ${USERFRONT_BOOT_WARMUP_ATTEMPTS} readiness attempts" >&2 return 0 fi started_at="$(date +%s)" echo "[userfront-boot] one-shot warmup starting locales=\"${USERFRONT_BOOT_WARMUP_LOCALES}\" viewports=\"${USERFRONT_BOOT_WARMUP_VIEWPORTS}\"" >&2 for locale in $USERFRONT_BOOT_WARMUP_LOCALES; do for viewport in $USERFRONT_BOOT_WARMUP_VIEWPORTS; do warm_get "/${locale}/signin" "$locale" "$viewport" || true done done for asset in \ / \ /flutter_bootstrap.js \ /canvaskit/skwasm.js \ /canvaskit/skwasm.wasm \ /canvaskit/skwasm_heavy.js \ /canvaskit/skwasm_heavy.wasm \ /assets/AssetManifest.bin.json \ /assets/FontManifest.json do wget -qO- "http://127.0.0.1:${USERFRONT_INTERNAL_PORT}${asset}" >/dev/null 2>&1 || true done warm_flutter_bootstrap_assets finished_at="$(date +%s)" elapsed_seconds=$((finished_at - started_at)) echo "[userfront-boot] one-shot warmup completed in ${elapsed_seconds}s" >&2 } set -- flutter run \ -d web-server \ --web-hostname 0.0.0.0 \ --web-port "${USERFRONT_INTERNAL_PORT}" \ --wasm \ --dart-define=BACKEND_URL="${BACKEND_URL:-}" \ --dart-define=CLIENT_LOG_DEBUG="${CLIENT_LOG_DEBUG:-false}" \ --dart-define=APP_ENV="${APP_ENV:-dev}" \ --dart-define=USERFRONT_URL="${USERFRONT_URL:-}" \ ${USERFRONT_FLUTTER_RUN_FLAGS} \ --no-web-resources-cdn mkdir -p "$(dirname "$USERFRONT_BOOT_LOG")" rm -f "$USERFRONT_BOOT_LOG" "$USERFRONT_BOOT_LOG_PIPE" mkfifo "$USERFRONT_BOOT_LOG_PIPE" tee "$USERFRONT_BOOT_LOG" < "$USERFRONT_BOOT_LOG_PIPE" & tee_pid="$!" "$@" > "$USERFRONT_BOOT_LOG_PIPE" 2>&1 & flutter_pid="$!" terminate() { kill "$flutter_pid" 2>/dev/null || true kill "$tee_pid" 2>/dev/null || true wait "$flutter_pid" 2>/dev/null || true wait "$tee_pid" 2>/dev/null || true rm -f "$USERFRONT_BOOT_LOG_PIPE" } trap terminate INT TERM warm_userfront_once "$flutter_pid" set +e wait "$flutter_pid" flutter_status="$?" wait "$tee_pid" 2>/dev/null || true rm -f "$USERFRONT_BOOT_LOG_PIPE" exit "$flutter_status"