From 974d33b32269eefa4472960c5b4dd1788674f957 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 5 Aug 2025 11:51:48 +0000 Subject: [PATCH] Document environment variable precedence and API configuration scheme Add comprehensive documentation explaining the order of precedence for environment variables in TimeSafari project. Covers shell script overrides, platform-specific configurations, .env file usage, and API alignment between claim and partner APIs. Includes troubleshooting guide and best practices for maintaining consistent environment configuration across development, test, and production environments. --- .../environment-variable-precedence.md | 338 ++++++++++++++++++ .../platforms/android-custom-api-ip.md | 3 + scripts/build-android.sh | 4 +- scripts/build-ios.sh | 3 +- scripts/common.sh | 10 +- 5 files changed, 351 insertions(+), 7 deletions(-) create mode 100644 docs/build-system/environment-variable-precedence.md diff --git a/docs/build-system/environment-variable-precedence.md b/docs/build-system/environment-variable-precedence.md new file mode 100644 index 00000000..ee5f5b39 --- /dev/null +++ b/docs/build-system/environment-variable-precedence.md @@ -0,0 +1,338 @@ +# Environment Variable Precedence and API Configuration + +**Date:** August 4, 2025 +**Author:** Matthew Raymer + +## Overview + +This document explains the order of precedence for environment variables in the +TimeSafari project, how `.env` files are used, and the API configuration scheme +for different environments. + +## Order of Precedence (Highest to Lowest) + +### 1. Shell Script Overrides (Highest Priority) + +Shell scripts can override environment variables for platform-specific needs: + +```bash +# scripts/common.sh - setup_build_env() +if [ "$BUILD_MODE" = "development" ]; then + export VITE_DEFAULT_ENDORSER_API_SERVER="http://localhost:3000" + export VITE_DEFAULT_PARTNER_API_SERVER="http://localhost:3000" +fi +``` + +### 2. Platform-Specific Overrides (High Priority) + +Platform-specific build scripts can override for mobile development: + +```bash +# scripts/build-android.sh +if [ "$BUILD_MODE" = "development" ]; then + export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000" + export VITE_DEFAULT_PARTNER_API_SERVER="http://10.0.2.2:3000" +fi +``` + +### 3. Environment-Specific .env Files (Medium Priority) + +Environment-specific `.env` files provide environment-specific defaults: + +```bash +# .env.development, .env.test, .env.production +VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 +VITE_DEFAULT_PARTNER_API_SERVER=http://localhost:3000 +``` + +### 4. Fallback .env File (Low Priority) + +General `.env` file provides project-wide defaults: + +```bash +# .env (if exists) +VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 +``` + +### 5. app.ts Constants (Lowest Priority - Fallback) + +Hardcoded constants in `src/constants/app.ts` provide safety nets: + +```typescript +export const DEFAULT_ENDORSER_API_SERVER = + import.meta.env.VITE_DEFAULT_ENDORSER_API_SERVER || + AppString.PROD_ENDORSER_API_SERVER; +``` + +## Build Process Flow + +### 1. Shell Scripts Set Base Values + +```bash +# scripts/common.sh +setup_build_env() { + if [ "$BUILD_MODE" = "development" ]; then + export VITE_DEFAULT_ENDORSER_API_SERVER="http://localhost:3000" + export VITE_DEFAULT_PARTNER_API_SERVER="http://localhost:3000" + fi +} +``` + +### 2. Platform-Specific Overrides + +```bash +# scripts/build-android.sh +if [ "$BUILD_MODE" = "development" ]; then + export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000" + export VITE_DEFAULT_PARTNER_API_SERVER="http://10.0.2.2:3000" +fi +``` + +### 3. Load .env Files + +```bash +# scripts/build-web.sh +local env_file=".env.$BUILD_MODE" # .env.development, .env.test, .env.production +if [ -f "$env_file" ]; then + load_env_file "$env_file" +fi + +# Fallback to .env +if [ -f ".env" ]; then + load_env_file ".env" +fi +``` + +### 4. Vite Processes Environment + +```typescript +// vite.config.common.mts +dotenv.config(); // Loads .env files +``` + +### 5. Application Uses Values + +```typescript +// src/constants/app.ts +export const DEFAULT_ENDORSER_API_SERVER = + import.meta.env.VITE_DEFAULT_ENDORSER_API_SERVER || + AppString.PROD_ENDORSER_API_SERVER; +``` + +## API Configuration Scheme + +### Environment Configuration Summary + +| Environment | Endorser API (Claims) | Partner API | Image API | +|-------------|----------------------|-------------|-----------| +| **Development** | `http://localhost:3000` | `http://localhost:3000` | `https://image-api.timesafari.app` | +| **Test** | `https://test-api.endorser.ch` | `https://test-partner-api.endorser.ch` | `https://image-api.timesafari.app` | +| **Production** | `https://api.endorser.ch` | `https://partner-api.endorser.ch` | `https://image-api.timesafari.app` | + +### Mobile Development Overrides + +#### Android Development + +- **Emulator**: `http://10.0.2.2:3000` (Android emulator default) +- **Physical Device**: `http://{CUSTOM_IP}:3000` (Custom IP for physical device) + +#### iOS Development + +- **Simulator**: `http://localhost:3000` (iOS simulator default) +- **Physical Device**: `http://{CUSTOM_IP}:3000` (Custom IP for physical device) + +## .env File Structure + +### .env.development +```bash +# ========================================== +# DEVELOPMENT ENVIRONMENT CONFIGURATION +# ========================================== +# API Server Configuration: +# - Endorser API (Claims): Local development server +# - Partner API: Local development server (aligned with claims) +# - Image API: Test server (shared for development) +# ========================================== + +# Only the variables that start with VITE_ are seen in the application import.meta.env in Vue. + +# iOS doesn't like spaces in the app title. +TIME_SAFARI_APP_TITLE="TimeSafari_Dev" +VITE_APP_SERVER=http://localhost:8080 + +# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production). +VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F + +# API Servers (Development - Local) +VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 +VITE_DEFAULT_PARTNER_API_SERVER=http://localhost:3000 + +# Image API (Test server for development) +VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app + +# Push Server (disabled for localhost) +#VITE_DEFAULT_PUSH_SERVER... can't be set up with localhost domain + +# Feature Flags +VITE_PASSKEYS_ENABLED=true +``` + +### .env.test +```bash +# ========================================== +# TEST ENVIRONMENT CONFIGURATION +# ========================================== +# API Server Configuration: +# - Endorser API (Claims): Test server +# - Partner API: Test server (aligned with claims) +# - Image API: Test server +# ========================================== + +# Only the variables that start with VITE_ are seen in the application import.meta.env in Vue. + +# iOS doesn't like spaces in the app title. +TIME_SAFARI_APP_TITLE="TimeSafari_Test" +VITE_APP_SERVER=https://test.timesafari.app + +# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production). +VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F + +# API Servers (Test Environment) +VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch +VITE_DEFAULT_PARTNER_API_SERVER=https://test-partner-api.endorser.ch + +# Image API (Test server) +VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app + +# Push Server (Test) +VITE_DEFAULT_PUSH_SERVER=https://test.timesafari.app + +# Feature Flags +VITE_PASSKEYS_ENABLED=true +``` + +### .env.production +```bash +# ========================================== +# PRODUCTION ENVIRONMENT CONFIGURATION +# ========================================== +# API Server Configuration: +# - Endorser API (Claims): Production server +# - Partner API: Production server (aligned with claims) +# - Image API: Production server +# ========================================== + +# Only the variables that start with VITE_ are seen in the application import.meta.env in Vue. + +# App Server +VITE_APP_SERVER=https://timesafari.app + +# This is the claim ID for actions in the BVC project. +VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01GXYPFF7FA03NXKPYY142PY4H + +# API Servers (Production Environment) +VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch +VITE_DEFAULT_PARTNER_API_SERVER=https://partner-api.endorser.ch + +# Image API (Production server) +VITE_DEFAULT_IMAGE_API_SERVER=https://image-api.timesafari.app + +# Push Server (Production) +VITE_DEFAULT_PUSH_SERVER=https://timesafari.app +``` + +## Key Principles + +### 1. API Alignment +- **Partner API** values follow the same pattern as **Claim API** (Endorser API) +- Both APIs use the same environment-specific endpoints +- This ensures consistency across the application + +### 2. Platform Flexibility +- Shell scripts can override for platform-specific needs +- Android emulator uses `10.0.2.2:3000` +- iOS simulator uses `localhost:3000` +- Physical devices use custom IP addresses + +### 3. Environment Isolation +- Each environment has its own `.env` file +- Test environment uses test APIs +- Development environment uses local APIs +- Production environment uses production APIs + +### 4. Safety Nets +- Hardcoded constants in `app.ts` provide fallbacks +- Multiple layers of configuration prevent failures +- Clear precedence order ensures predictable behavior + +## Usage Examples + +### Development Build +```bash +# Uses .env.development + shell script overrides +npm run build:web -- --mode development +``` + +### Test Build +```bash +# Uses .env.test + shell script overrides +npm run build:web -- --mode test +``` + +### Production Build +```bash +# Uses .env.production + shell script overrides +npm run build:web -- --mode production +``` + +### Android Development +```bash +# Uses .env.development + Android-specific overrides +./scripts/build-android.sh --dev +``` + +### iOS Development +```bash +# Uses .env.development + iOS-specific overrides +./scripts/build-ios.sh --dev +``` + +## Troubleshooting + +### Environment Variable Debugging +```bash +# Show current environment variables +./scripts/build-web.sh --env + +# Check specific variable +echo $VITE_DEFAULT_ENDORSER_API_SERVER +``` + +### Common Issues + +1. **Wrong API Server**: Check if shell script overrides are correct +2. **Missing .env File**: Ensure environment-specific .env file exists +3. **Platform-Specific Issues**: Verify platform overrides in build scripts +4. **Vite Not Loading**: Check if `dotenv.config()` is called + +### Validation +```bash +# Validate environment configuration +npm run test-env +``` + +## Best Practices + +1. **Always use environment-specific .env files** for different environments +2. **Keep shell script overrides minimal** and platform-specific +3. **Document API alignment** in .env file headers +4. **Use hardcoded fallbacks** in `app.ts` for safety +5. **Test all environments** before deployment +6. **Validate configuration** with test scripts + +## Related Documentation + +- [Build System Overview](../build-system/README.md) +- [Android Custom API IP](../platforms/android-custom-api-ip.md) +- [API Configuration](../api-configuration.md) +- [Environment Setup](../environment-setup.md) \ No newline at end of file diff --git a/docs/build-system/platforms/android-custom-api-ip.md b/docs/build-system/platforms/android-custom-api-ip.md index a741fba9..0d2eadee 100644 --- a/docs/build-system/platforms/android-custom-api-ip.md +++ b/docs/build-system/platforms/android-custom-api-ip.md @@ -144,14 +144,17 @@ The build system handles API server configuration as follows: ```bash # Development mode with Android emulator default (10.0.2.2) export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000" +export VITE_DEFAULT_PARTNER_API_SERVER="http://10.0.2.2:3000" npm run build:capacitor -- --mode development # Development mode with iOS simulator default (localhost) export VITE_DEFAULT_ENDORSER_API_SERVER="http://localhost:3000" +export VITE_DEFAULT_PARTNER_API_SERVER="http://localhost:3000" npm run build:capacitor -- --mode development # Development mode with custom IP export VITE_DEFAULT_ENDORSER_API_SERVER="http://192.168.1.100:3000" +export VITE_DEFAULT_PARTNER_API_SERVER="http://192.168.1.100:3000" npm run build:capacitor -- --mode development ``` diff --git a/scripts/build-android.sh b/scripts/build-android.sh index ba4d3ac6..53ada97e 100755 --- a/scripts/build-android.sh +++ b/scripts/build-android.sh @@ -186,15 +186,17 @@ log_info "Build type: $BUILD_TYPE" # Setup environment for Capacitor build setup_build_env "capacitor" -# Override API server for Android development +# Override API servers for Android development if [ "$BUILD_MODE" = "development" ]; then if [ -n "$CUSTOM_API_IP" ]; then # Use custom IP for physical device development export VITE_DEFAULT_ENDORSER_API_SERVER="http://${CUSTOM_API_IP}:3000" + export VITE_DEFAULT_PARTNER_API_SERVER="http://${CUSTOM_API_IP}:3000" log_info "Android development mode: Using custom IP ${CUSTOM_API_IP} for physical device" else # Use Android emulator IP (10.0.2.2) for Android development export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000" + export VITE_DEFAULT_PARTNER_API_SERVER="http://10.0.2.2:3000" log_debug "Android development mode: Using 10.0.2.2 for emulator" fi fi diff --git a/scripts/build-ios.sh b/scripts/build-ios.sh index 33e78e3b..9c3b2118 100755 --- a/scripts/build-ios.sh +++ b/scripts/build-ios.sh @@ -313,10 +313,11 @@ log_info "Build type: $BUILD_TYPE" # Setup environment for Capacitor build setup_build_env "capacitor" -# Override API server for iOS development when custom IP is specified +# Override API servers for iOS development when custom IP is specified if [ "$BUILD_MODE" = "development" ] && [ -n "$CUSTOM_API_IP" ]; then # Use custom IP for physical device development export VITE_DEFAULT_ENDORSER_API_SERVER="http://${CUSTOM_API_IP}:3000" + export VITE_DEFAULT_PARTNER_API_SERVER="http://${CUSTOM_API_IP}:3000" log_info "iOS development mode: Using custom IP ${CUSTOM_API_IP} for physical device" fi diff --git a/scripts/common.sh b/scripts/common.sh index 7b106c8d..ac06e315 100755 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -200,19 +200,19 @@ setup_build_env() { # For Capacitor development, use localhost by default # Android builds will override this in build-android.sh export VITE_DEFAULT_ENDORSER_API_SERVER="http://localhost:3000" - log_debug "Development mode: Using localhost for Endorser API, production for Image/Partner APIs" + export VITE_DEFAULT_PARTNER_API_SERVER="http://localhost:3000" + log_debug "Development mode: Using localhost for Endorser and Partner APIs" export VITE_DEFAULT_IMAGE_API_SERVER="https://image-api.timesafari.app" - export VITE_DEFAULT_PARTNER_API_SERVER="https://partner-api.endorser.ch" elif [ "$BUILD_MODE" = "test" ]; then export VITE_DEFAULT_ENDORSER_API_SERVER="https://test-api.endorser.ch" + export VITE_DEFAULT_PARTNER_API_SERVER="https://test-partner-api.endorser.ch" + log_debug "Test mode: Using test Endorser and Partner APIs" export VITE_DEFAULT_IMAGE_API_SERVER="https://image-api.timesafari.app" - export VITE_DEFAULT_PARTNER_API_SERVER="https://partner-api.endorser.ch" - log_debug "Test mode: Using test Endorser API, production for Image/Partner APIs" elif [ "$BUILD_MODE" = "production" ]; then export VITE_DEFAULT_ENDORSER_API_SERVER="https://api.endorser.ch" - export VITE_DEFAULT_IMAGE_API_SERVER="https://image-api.timesafari.app" export VITE_DEFAULT_PARTNER_API_SERVER="https://partner-api.endorser.ch" log_debug "Production mode: Using production API servers" + export VITE_DEFAULT_IMAGE_API_SERVER="https://image-api.timesafari.app" fi # Log environment setup