#!/usr/bin/env bash # Fill a local .env from .env.example without clobbering values already set. # Blank keys and replace-with-* placeholders are injected: # computer sudo + local-dev password, zh-TW UI, random app secrets. set -euo pipefail repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" ENV_FILE="${ENV_FILE:-$repo_dir/.env}" EXAMPLE_FILE="${EXAMPLE_FILE:-$repo_dir/.env.example}" LOCAL_COMPUTER_PASSWORD="${LOCAL_COMPUTER_PASSWORD:-bangso}" LOCAL_COMPUTER_SUDO="${LOCAL_COMPUTER_SUDO:-1}" LOCAL_UI_LOCALE="${LOCAL_UI_LOCALE:-zh-TW}" if [[ ! -f "$EXAMPLE_FILE" ]]; then echo "Missing $EXAMPLE_FILE. Run this from the repository root." >&2 exit 1 fi if ! command -v openssl >/dev/null 2>&1; then echo "Missing required command: openssl" >&2 exit 1 fi is_placeholder() { local value="$1" [[ -z "$value" || "$value" == replace-with-* ]] } read_key() { local file="$1" local key="$2" local value="" line [[ -f "$file" ]] || return 0 while IFS= read -r line || [[ -n "$line" ]]; do line="${line%$'\r'}" case "$line" in "${key}="*) value="${line#${key}=}" ;; esac done < "$file" printf '%s' "$value" } upsert() { local key="$1" local value="$2" local tmp line emitted=0 tmp="$(mktemp "${ENV_FILE}.XXXXXX")" if [[ -f "$ENV_FILE" ]]; then while IFS= read -r line || [[ -n "$line" ]]; do line="${line%$'\r'}" case "$line" in "${key}="*) if [[ "$emitted" -eq 0 ]]; then printf '%s=%s\n' "$key" "$value" emitted=1 fi ;; *) printf '%s\n' "$line" ;; esac done < "$ENV_FILE" > "$tmp" fi if [[ "$emitted" -eq 0 ]]; then printf '%s=%s\n' "$key" "$value" >> "$tmp" fi mv "$tmp" "$ENV_FILE" } process_value() { case "$1" in BETTER_AUTH_SECRET) printf '%s' "${BETTER_AUTH_SECRET-}" ;; ENCRYPTION_KEY) printf '%s' "${ENCRYPTION_KEY-}" ;; SANDBOX_SUPERVISOR_TOKEN) printf '%s' "${SANDBOX_SUPERVISOR_TOKEN-}" ;; SCREEN_PROXY_SECRET) printf '%s' "${SCREEN_PROXY_SECRET-}" ;; COMPUTER_ALLOW_SUDO) printf '%s' "${COMPUTER_ALLOW_SUDO-}" ;; COMPUTER_USER_PASSWORD) printf '%s' "${COMPUTER_USER_PASSWORD-}" ;; VITE_DEFAULT_UI_LOCALE) printf '%s' "${VITE_DEFAULT_UI_LOCALE-}" ;; esac } fill() { local key="$1" local fallback="$2" local current proc val current="$(read_key "$ENV_FILE" "$key")" proc="$(process_value "$key")" if ! is_placeholder "$current"; then return 0 fi if [[ -n "$proc" ]]; then val="$proc" elif [[ "$fallback" == "--random" ]]; then val="$(openssl rand -hex 32)" else val="$fallback" fi upsert "$key" "$val" printf 'injected %s\n' "$key" } if [[ ! -f "$ENV_FILE" ]]; then umask 077 cp "$EXAMPLE_FILE" "$ENV_FILE" chmod 600 "$ENV_FILE" echo "created $ENV_FILE from $(basename "$EXAMPLE_FILE")" fi fill BETTER_AUTH_SECRET --random fill ENCRYPTION_KEY --random fill SANDBOX_SUPERVISOR_TOKEN --random fill SCREEN_PROXY_SECRET --random fill COMPUTER_ALLOW_SUDO "$LOCAL_COMPUTER_SUDO" fill COMPUTER_USER_PASSWORD "$LOCAL_COMPUTER_PASSWORD" fill VITE_DEFAULT_UI_LOCALE "$LOCAL_UI_LOCALE" chmod 600 "$ENV_FILE"