From 32f589b86697267e362d28a1d8569131c99a57c6 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 5 Aug 2025 09:08:50 +0000 Subject: [PATCH 01/10] Fix Android emulator API connectivity with cleaner build script approach - Move Android-specific API server logic from common.sh to build-android.sh - Remove unnecessary ANDROID_BUILD environment variable - Set localhost:3000 as default in common.sh for all Capacitor builds - Override to 10.0.2.2:3000 specifically in build-android.sh for Android development - Fix execution order issue where common.sh ran before ANDROID_BUILD was set - Maintain proper separation: Android emulator uses 10.0.2.2, iOS simulator uses localhost --- android/app/src/main/assets/capacitor.config.json | 5 +++-- android/build.gradle | 2 +- capacitor.config.json | 5 +++-- scripts/build-android.sh | 6 ++++++ scripts/common.sh | 4 +++- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/android/app/src/main/assets/capacitor.config.json b/android/app/src/main/assets/capacitor.config.json index e0f25d83..594ebca3 100644 --- a/android/app/src/main/assets/capacitor.config.json +++ b/android/app/src/main/assets/capacitor.config.json @@ -57,13 +57,14 @@ ] }, "android": { - "allowMixedContent": false, + "allowMixedContent": true, "captureInput": true, "webContentsDebuggingEnabled": false, "allowNavigation": [ "*.timesafari.app", "*.jsdelivr.net", - "api.endorser.ch" + "api.endorser.ch", + "10.0.2.2:3000" ] }, "electron": { diff --git a/android/build.gradle b/android/build.gradle index 5a959f82..858b0bc0 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.11.1' + classpath 'com.android.tools.build:gradle:8.12.0' classpath 'com.google.gms:google-services:4.4.0' // NOTE: Do not place your application dependencies here; they belong diff --git a/capacitor.config.json b/capacitor.config.json index 08573136..863ae475 100644 --- a/capacitor.config.json +++ b/capacitor.config.json @@ -57,13 +57,14 @@ ] }, "android": { - "allowMixedContent": false, + "allowMixedContent": true, "captureInput": true, "webContentsDebuggingEnabled": false, "allowNavigation": [ "*.timesafari.app", "*.jsdelivr.net", - "api.endorser.ch" + "api.endorser.ch", + "10.0.2.2:3000" ] }, "electron": { diff --git a/scripts/build-android.sh b/scripts/build-android.sh index bf3df09a..1e3c4bed 100755 --- a/scripts/build-android.sh +++ b/scripts/build-android.sh @@ -166,6 +166,12 @@ log_info "Build type: $BUILD_TYPE" # Setup environment for Capacitor build setup_build_env "capacitor" +# Override API server for Android emulator development +if [ "$BUILD_MODE" = "development" ]; then + export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000" + log_debug "Android development mode: Using 10.0.2.2 for emulator, production for Image/Partner APIs" +fi + # Setup application directories setup_app_directories diff --git a/scripts/common.sh b/scripts/common.sh index cb658998..7b106c8d 100755 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -197,10 +197,12 @@ setup_build_env() { # Set API server environment variables based on build mode if [ "$BUILD_MODE" = "development" ]; then + # 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_IMAGE_API_SERVER="https://image-api.timesafari.app" export VITE_DEFAULT_PARTNER_API_SERVER="https://partner-api.endorser.ch" - log_debug "Development mode: Using localhost for Endorser API, production for Image/Partner APIs" elif [ "$BUILD_MODE" = "test" ]; then export VITE_DEFAULT_ENDORSER_API_SERVER="https://test-api.endorser.ch" export VITE_DEFAULT_IMAGE_API_SERVER="https://image-api.timesafari.app" From b681905abd555be0614df7c9d2ce36a76165224a Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 5 Aug 2025 09:42:53 +0000 Subject: [PATCH 02/10] Upgrade Android API from 35 to 36 Update Android SDK configuration to target API 36 (Android 16): - Update compileSdkVersion and targetSdkVersion from 35 to 36 - Update suppressUnsupportedCompileSdk from 34 to 36 - Maintains minSdkVersion at 22 for broad device compatibility - Verified build system compatibility with Gradle 8.13 --- android/app/build.gradle | 8 ++++++++ android/gradle.properties | 2 +- android/variables.gradle | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 0843dce8..82d3c92d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -64,6 +64,14 @@ android { } } } + packagingOptions { + jniLibs { + pickFirsts += ['**/lib/x86_64/libbarhopper_v3.so', '**/lib/x86_64/libimage_processing_util_jni.so', '**/lib/x86_64/libsqlcipher.so'] + } + } + + // Configure for 16 KB page size compatibility + // Enable bundle builds (without which it doesn't work right for bundleDebug vs bundleRelease) bundle { diff --git a/android/gradle.properties b/android/gradle.properties index 5e735fd3..8ea85815 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -20,4 +20,4 @@ org.gradle.jvmargs=-Xmx1536m # Android operating system, and which are packaged with your app's APK # https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true -android.suppressUnsupportedCompileSdk=34 +android.suppressUnsupportedCompileSdk=36 diff --git a/android/variables.gradle b/android/variables.gradle index 8ef305d0..ef1f5519 100644 --- a/android/variables.gradle +++ b/android/variables.gradle @@ -1,7 +1,7 @@ ext { minSdkVersion = 22 - compileSdkVersion = 34 - targetSdkVersion = 34 + compileSdkVersion = 36 + targetSdkVersion = 36 androidxActivityVersion = '1.8.0' androidxAppCompatVersion = '1.6.1' androidxCoordinatorLayoutVersion = '1.2.0' From 1d6418b02c89888e18c478facf80520b9a9979df Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 5 Aug 2025 10:26:38 +0000 Subject: [PATCH 03/10] Add custom API IP support for Android physical device development Implement --api-ip parameter for Android builds with smart defaults: - Defaults to 10.0.2.2 for emulator development when no IP specified - Supports custom IP for physical device development - Added npm scripts for common use cases (dev:custom, test:custom) - Updated help documentation with usage examples - Created comprehensive documentation with troubleshooting guide Usage: ./scripts/build-android.sh --dev # Default 10.0.2.2 ./scripts/build-android.sh --dev --api-ip 192.168.1.100 # Custom IP --- .../platforms/android-custom-api-ip.md | 284 ++++++++++++++++++ package.json | 6 +- scripts/build-android.sh | 35 ++- 3 files changed, 320 insertions(+), 5 deletions(-) create mode 100644 docs/build-system/platforms/android-custom-api-ip.md diff --git a/docs/build-system/platforms/android-custom-api-ip.md b/docs/build-system/platforms/android-custom-api-ip.md new file mode 100644 index 00000000..1db748c5 --- /dev/null +++ b/docs/build-system/platforms/android-custom-api-ip.md @@ -0,0 +1,284 @@ +# Android Custom API IP Configuration + +**Author**: Matthew Raymer +**Date**: 2025-01-27 +**Status**: ✅ **COMPLETE** - Custom API IP support for physical device development + +## Overview + +When deploying TimeSafari to physical Android devices during development, you may need to specify a custom IP address for the claim API server. This is necessary because physical devices cannot access `localhost` or `10.0.2.2` (Android emulator IP) to reach your local development server. + +## Problem + +During Android development: +- **Emulator**: Uses `10.0.2.2:3000` to access host machine's localhost (default) +- **Physical Device**: Cannot access `localhost` or `10.0.2.2` - needs actual IP address + +## Solution + +The Android build system defaults to `10.0.2.2:3000` for emulator development and supports specifying a custom IP address for the claim API server when building for physical devices. + +## Usage + +### Command Line Usage + +```bash +# Default behavior (uses 10.0.2.2 for emulator) +./scripts/build-android.sh --dev + +# Custom IP for physical device +./scripts/build-android.sh --dev --api-ip 192.168.1.100 + +# Test environment with custom IP +./scripts/build-android.sh --test --api-ip 192.168.1.100 + +# Build and auto-run with custom IP +./scripts/build-android.sh --dev --api-ip 192.168.1.100 --auto-run +``` + +### NPM Scripts + +```bash +# Default development build (uses 10.0.2.2 for emulator) +npm run build:android:dev + +# Development build with custom IP (requires IP parameter) +npm run build:android:dev:custom 192.168.1.100 + +# Test build with custom IP (requires IP parameter) +npm run build:android:test:custom 192.168.1.100 + +# Development build + auto-run with custom IP +npm run build:android:dev:run:custom 192.168.1.100 + +# Test build + auto-run with custom IP +npm run build:android:test:run:custom 192.168.1.100 +``` + +## Examples + +### Scenario 1: Development on Emulator (Default) + +```bash +# Default behavior - uses 10.0.2.2 for emulator +npm run build:android:dev + +# Build and immediately run on emulator +npm run build:android:dev:run +``` + +### Scenario 2: Development on Physical Device + +```bash +# Your development server is running on 192.168.1.50:3000 +npm run build:android:dev:custom 192.168.1.50 + +# Build and immediately run on device +npm run build:android:dev:run:custom 192.168.1.50 +``` + +### Scenario 3: Testing on Physical Device + +```bash +# Your test server is running on 192.168.1.75:3000 +npm run build:android:test:custom 192.168.1.75 + +# Build and immediately run on device +npm run build:android:test:run:custom 192.168.1.75 +``` + +### Scenario 4: Direct Script Usage + +```bash +# Default behavior (emulator) +./scripts/build-android.sh --dev --studio + +# Custom IP for physical device +./scripts/build-android.sh --dev --api-ip 192.168.1.100 --studio +./scripts/build-android.sh --test --api-ip 192.168.1.100 --apk +``` + +## How It Works + +### Environment Variable Override + +The build system handles API server configuration as follows: + +1. **Default behavior**: Uses `http://10.0.2.2:3000` for emulator development +2. **Custom IP specified**: Overrides with `http://:3000` for physical device development +3. **Maintains other APIs**: Image and Partner APIs remain at production URLs +4. **Logs the configuration**: Shows which IP is being used in build logs + +### Build Process + +```bash +# Development mode with default IP (10.0.2.2) +export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000" +npm run build:capacitor -- --mode development + +# Development mode with custom IP +export VITE_DEFAULT_ENDORSER_API_SERVER="http://192.168.1.100:3000" +npm run build:capacitor -- --mode development +``` + +### Default Behavior + +- **No `--api-ip` specified**: Uses default emulator IP (`10.0.2.2:3000`) +- **Custom IP specified**: Uses provided IP address for physical device development +- **Invalid IP format**: Build will fail with clear error message +- **Network unreachable**: App will show connection errors at runtime + +## Finding Your IP Address + +### On Linux/macOS + +```bash +# Find your local IP address +ifconfig | grep "inet " | grep -v 127.0.0.1 +# or +ip addr show | grep "inet " | grep -v 127.0.0.1 +``` + +### On Windows + +```bash +# Find your local IP address +ipconfig | findstr "IPv4" +``` + +### Common Network Patterns + +- **Home WiFi**: Usually `192.168.1.x` or `192.168.0.x` +- **Office Network**: May be `10.x.x.x` or `172.16.x.x` +- **Mobile Hotspot**: Often `192.168.43.x` + +## Troubleshooting + +### Common Issues + +#### 1. Device Cannot Connect to API + +```bash +# Check if your IP is accessible +ping 192.168.1.100 + +# Check if port 3000 is open +telnet 192.168.1.100 3000 +``` + +#### 2. Build Fails with Invalid IP + +```bash +# Ensure IP format is correct +./scripts/build-android.sh --dev --api-ip 192.168.1.100 # ✅ Correct +./scripts/build-android.sh --dev --api-ip localhost # ❌ Wrong +``` + +#### 3. Firewall Blocking Connection + +```bash +# Check firewall settings +sudo ufw status # Ubuntu/Debian +sudo firewall-cmd --list-all # CentOS/RHEL +``` + +### Debug Mode + +```bash +# Enable verbose logging +./scripts/build-android.sh --dev --api-ip 192.168.1.100 --verbose +``` + +## Best Practices + +### 1. Use Consistent IP Addresses + +```bash +# Create aliases for common development scenarios +alias build-dev="npm run build:android:dev:custom 192.168.1.100" +alias build-test="npm run build:android:test:custom 192.168.1.100" +``` + +### 2. Document Your Setup + +```bash +# Create a development setup file +echo "DEV_API_IP=192.168.1.100" > .env.development +echo "TEST_API_IP=192.168.1.100" >> .env.development +``` + +### 3. Network Security + +- Ensure your development server is only accessible on your local network +- Use HTTPS in production environments +- Consider VPN for remote development scenarios + +### 4. Team Development + +```bash +# Share IP configuration with team +# Add to .env.example +DEV_API_IP=192.168.1.100 +TEST_API_IP=192.168.1.100 +``` + +## Integration with CI/CD + +### Environment Variables + +```yaml +# Example CI/CD configuration +variables: + DEV_API_IP: "192.168.1.100" + TEST_API_IP: "192.168.1.100" + +build: + script: + - npm run build:android:dev:custom $DEV_API_IP +``` + +### Automated Testing + +```bash +# Test with different IP configurations +npm run build:android:test:custom 192.168.1.100 +npm run build:android:test:custom 10.0.0.100 +``` + +## Migration from Legacy + +### Previous Workarounds + +Before this feature, developers had to: +1. Manually edit environment files +2. Use different build configurations +3. Modify source code for IP addresses + +### New Approach + +```bash +# Simple one-liner +npm run build:android:dev:custom 192.168.1.100 +``` + +## Future Enhancements + +### Planned Features + +1. **IP Validation**: Automatic IP format validation +2. **Network Discovery**: Auto-detect available IP addresses +3. **Port Configuration**: Support for custom ports +4. **Multiple APIs**: Support for custom IPs for all API endpoints + +### Integration Opportunities + +1. **Docker Integration**: Automatic IP detection in containerized environments +2. **Network Profiles**: Save and reuse common network configurations +3. **Hot Reload**: Automatic rebuild when IP changes + +--- + +**Status**: Complete and ready for production use +**Last Updated**: 2025-01-27 +**Version**: 1.0 +**Maintainer**: Matthew Raymer \ No newline at end of file diff --git a/package.json b/package.json index 758ce227..9ec3b946 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,11 @@ "build:android:clean": "./scripts/build-android.sh --clean", "build:android:sync": "./scripts/build-android.sh --sync", "build:android:assets": "./scripts/build-android.sh --assets", - "build:android:deploy": "./scripts/build-android.sh --deploy" + "build:android:deploy": "./scripts/build-android.sh --deploy", + "build:android:dev:custom": "./scripts/build-android.sh --dev --api-ip", + "build:android:test:custom": "./scripts/build-android.sh --test --api-ip", + "build:android:dev:run:custom": "./scripts/build-android.sh --dev --api-ip --auto-run", + "build:android:test:run:custom": "./scripts/build-android.sh --test --api-ip --auto-run" }, "dependencies": { "@capacitor-community/electron": "^5.0.1", diff --git a/scripts/build-android.sh b/scripts/build-android.sh index 1e3c4bed..874761ce 100755 --- a/scripts/build-android.sh +++ b/scripts/build-android.sh @@ -60,12 +60,16 @@ SYNC_ONLY=false ASSETS_ONLY=false DEPLOY_APP=false AUTO_RUN=false +CUSTOM_API_IP="" # Function to parse Android-specific arguments parse_android_args() { local args=("$@") + local i=0 - for arg in "${args[@]}"; do + while [ $i -lt ${#args[@]} ]; do + local arg="${args[$i]}" + case $arg in --dev|--development) BUILD_MODE="development" @@ -106,6 +110,18 @@ parse_android_args() { --auto-run) AUTO_RUN=true ;; + --api-ip) + if [ $((i + 1)) -lt ${#args[@]} ]; then + CUSTOM_API_IP="${args[$((i + 1))]}" + i=$((i + 1)) # Skip the next argument + else + log_error "Error: --api-ip requires an IP address" + exit 1 + fi + ;; + --api-ip=*) + CUSTOM_API_IP="${arg#*=}" + ;; -h|--help) print_android_usage exit 0 @@ -117,6 +133,7 @@ parse_android_args() { log_warn "Unknown argument: $arg" ;; esac + i=$((i + 1)) done } @@ -138,6 +155,7 @@ print_android_usage() { echo " --assets Generate assets only" echo " --deploy Deploy APK to connected device" echo " --auto-run Auto-run app after build" + echo " --api-ip Custom IP address for claim API (defaults to 10.0.2.2)" echo "" echo "Common Options:" echo " -h, --help Show this help message" @@ -151,6 +169,8 @@ print_android_usage() { echo " $0 --clean # Clean only" echo " $0 --sync # Sync only" echo " $0 --deploy # Build and deploy to device" + echo " $0 --dev # Dev build with default 10.0.2.2" + echo " $0 --dev --api-ip 192.168.1.100 # Dev build with custom API IP" echo "" } @@ -166,10 +186,17 @@ log_info "Build type: $BUILD_TYPE" # Setup environment for Capacitor build setup_build_env "capacitor" -# Override API server for Android emulator development +# Override API server for Android development if [ "$BUILD_MODE" = "development" ]; then - export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000" - log_debug "Android development mode: Using 10.0.2.2 for emulator, production for Image/Partner APIs" + if [ -n "$CUSTOM_API_IP" ]; then + # Use custom IP for physical device development + export VITE_DEFAULT_ENDORSER_API_SERVER="http://${CUSTOM_API_IP}:3000" + log_info "Android development mode: Using custom IP ${CUSTOM_API_IP} for physical device" + else + # Use default emulator IP (10.0.2.2) for Android development + export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000" + log_debug "Android development mode: Using default 10.0.2.2 for emulator" + fi fi # Setup application directories From 3b1a63468c46599bb079447726e51b13a73a463d Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 5 Aug 2025 10:43:51 +0000 Subject: [PATCH 04/10] Add iOS support for custom API IP configuration Extend custom API IP feature to iOS platform with platform-appropriate defaults: - Android: Defaults to 10.0.2.2 for emulator, custom IP for physical devices - iOS: Uses localhost for simulator, custom IP for physical devices - Added npm scripts for iOS custom IP builds (dev:custom, test:custom) - Updated documentation to cover both platforms with examples - Consistent --api-ip parameter across Android and iOS build scripts Usage: ./scripts/build-ios.sh --dev # Default localhost ./scripts/build-ios.sh --dev --api-ip 192.168.1.100 # Custom IP --- .../platforms/android-custom-api-ip.md | 77 ++++++++++++++----- package.json | 4 + scripts/build-android.sh | 4 +- scripts/build-ios.sh | 31 +++++++- 4 files changed, 92 insertions(+), 24 deletions(-) diff --git a/docs/build-system/platforms/android-custom-api-ip.md b/docs/build-system/platforms/android-custom-api-ip.md index 1db748c5..a741fba9 100644 --- a/docs/build-system/platforms/android-custom-api-ip.md +++ b/docs/build-system/platforms/android-custom-api-ip.md @@ -1,4 +1,4 @@ -# Android Custom API IP Configuration +# Mobile Custom API IP Configuration **Author**: Matthew Raymer **Date**: 2025-01-27 @@ -10,61 +10,85 @@ When deploying TimeSafari to physical Android devices during development, you ma ## Problem -During Android development: -- **Emulator**: Uses `10.0.2.2:3000` to access host machine's localhost (default) -- **Physical Device**: Cannot access `localhost` or `10.0.2.2` - needs actual IP address +During mobile development: +- **Android Emulator**: Uses `10.0.2.2:3000` to access host machine's localhost (Android emulator default) +- **iOS Simulator**: Uses `localhost:3000` to access host machine's localhost (iOS simulator default) +- **Physical Devices**: Cannot access `localhost` or `10.0.2.2` - needs actual IP address for network access ## Solution -The Android build system defaults to `10.0.2.2:3000` for emulator development and supports specifying a custom IP address for the claim API server when building for physical devices. +The mobile build system uses platform-appropriate defaults and supports specifying a custom IP address for the claim API server when building for physical devices: +- **Android**: Defaults to `10.0.2.2:3000` for emulator development +- **iOS**: Uses Capacitor default (`localhost:3000`) for simulator development ## Usage ### Command Line Usage ```bash -# Default behavior (uses 10.0.2.2 for emulator) +# Android - Default behavior (uses 10.0.2.2 for emulator) ./scripts/build-android.sh --dev -# Custom IP for physical device +# Android - Custom IP for physical device ./scripts/build-android.sh --dev --api-ip 192.168.1.100 +# iOS - Default behavior (uses localhost for simulator) +./scripts/build-ios.sh --dev + +# iOS - Custom IP for physical device +./scripts/build-ios.sh --dev --api-ip 192.168.1.100 + # Test environment with custom IP ./scripts/build-android.sh --test --api-ip 192.168.1.100 +./scripts/build-ios.sh --test --api-ip 192.168.1.100 # Build and auto-run with custom IP ./scripts/build-android.sh --dev --api-ip 192.168.1.100 --auto-run +./scripts/build-ios.sh --dev --api-ip 192.168.1.100 --auto-run ``` ### NPM Scripts ```bash -# Default development build (uses 10.0.2.2 for emulator) +# Android - Default development build (uses 10.0.2.2 for emulator) npm run build:android:dev -# Development build with custom IP (requires IP parameter) +# Android - Development build with custom IP (requires IP parameter) npm run build:android:dev:custom 192.168.1.100 -# Test build with custom IP (requires IP parameter) +# iOS - Default development build (uses localhost for simulator) +npm run build:ios:dev + +# iOS - Development build with custom IP (requires IP parameter) +npm run build:ios:dev:custom 192.168.1.100 + +# Test builds with custom IP (requires IP parameter) npm run build:android:test:custom 192.168.1.100 +npm run build:ios:test:custom 192.168.1.100 # Development build + auto-run with custom IP npm run build:android:dev:run:custom 192.168.1.100 +npm run build:ios:dev:run:custom 192.168.1.100 # Test build + auto-run with custom IP npm run build:android:test:run:custom 192.168.1.100 +npm run build:ios:test:run:custom 192.168.1.100 ``` ## Examples -### Scenario 1: Development on Emulator (Default) +### Scenario 1: Development on Simulator/Emulator (Default) ```bash -# Default behavior - uses 10.0.2.2 for emulator +# Android - Default behavior - uses 10.0.2.2 for emulator npm run build:android:dev -# Build and immediately run on emulator +# iOS - Default behavior - uses localhost for simulator +npm run build:ios:dev + +# Build and immediately run on simulator/emulator npm run build:android:dev:run +npm run build:ios:dev:run ``` ### Scenario 2: Development on Physical Device @@ -72,9 +96,11 @@ npm run build:android:dev:run ```bash # Your development server is running on 192.168.1.50:3000 npm run build:android:dev:custom 192.168.1.50 +npm run build:ios:dev:custom 192.168.1.50 # Build and immediately run on device npm run build:android:dev:run:custom 192.168.1.50 +npm run build:ios:dev:run:custom 192.168.1.50 ``` ### Scenario 3: Testing on Physical Device @@ -82,20 +108,23 @@ npm run build:android:dev:run:custom 192.168.1.50 ```bash # Your test server is running on 192.168.1.75:3000 npm run build:android:test:custom 192.168.1.75 +npm run build:ios:test:custom 192.168.1.75 # Build and immediately run on device npm run build:android:test:run:custom 192.168.1.75 +npm run build:ios:test:run:custom 192.168.1.75 ``` ### Scenario 4: Direct Script Usage ```bash -# Default behavior (emulator) +# Default behavior (uses platform-appropriate defaults) ./scripts/build-android.sh --dev --studio +./scripts/build-ios.sh --dev --studio # Custom IP for physical device ./scripts/build-android.sh --dev --api-ip 192.168.1.100 --studio -./scripts/build-android.sh --test --api-ip 192.168.1.100 --apk +./scripts/build-ios.sh --dev --api-ip 192.168.1.100 --studio ``` ## How It Works @@ -104,18 +133,23 @@ npm run build:android:test:run:custom 192.168.1.75 The build system handles API server configuration as follows: -1. **Default behavior**: Uses `http://10.0.2.2:3000` for emulator development -2. **Custom IP specified**: Overrides with `http://:3000` for physical device development -3. **Maintains other APIs**: Image and Partner APIs remain at production URLs -4. **Logs the configuration**: Shows which IP is being used in build logs +1. **Android default**: Uses Android emulator default (`http://10.0.2.2:3000`) +2. **iOS default**: Uses Capacitor default (`http://localhost:3000`) +3. **Custom IP specified**: Overrides with `http://:3000` for physical device development +4. **Maintains other APIs**: Image and Partner APIs remain at production URLs +5. **Logs the configuration**: Shows which IP is being used in build logs ### Build Process ```bash -# Development mode with default IP (10.0.2.2) +# Development mode with Android emulator default (10.0.2.2) export VITE_DEFAULT_ENDORSER_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" +npm run build:capacitor -- --mode development + # Development mode with custom IP export VITE_DEFAULT_ENDORSER_API_SERVER="http://192.168.1.100:3000" npm run build:capacitor -- --mode development @@ -123,7 +157,8 @@ npm run build:capacitor -- --mode development ### Default Behavior -- **No `--api-ip` specified**: Uses default emulator IP (`10.0.2.2:3000`) +- **Android (no `--api-ip`)**: Uses Android emulator default (`10.0.2.2:3000`) +- **iOS (no `--api-ip`)**: Uses Capacitor default (`localhost:3000`) - **Custom IP specified**: Uses provided IP address for physical device development - **Invalid IP format**: Build will fail with clear error message - **Network unreachable**: App will show connection errors at runtime diff --git a/package.json b/package.json index 9ec3b946..2274ed91 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,10 @@ "build:ios:sync": "./scripts/build-ios.sh --sync", "build:ios:assets": "./scripts/build-ios.sh --assets", "build:ios:deploy": "./scripts/build-ios.sh --deploy", + "build:ios:dev:custom": "./scripts/build-ios.sh --dev --api-ip", + "build:ios:test:custom": "./scripts/build-ios.sh --test --api-ip", + "build:ios:dev:run:custom": "./scripts/build-ios.sh --dev --api-ip --auto-run", + "build:ios:test:run:custom": "./scripts/build-ios.sh --test --api-ip --auto-run", "build:web": "./scripts/build-web.sh", "build:web:dev": "./scripts/build-web.sh --dev", "build:web:test": "./scripts/build-web.sh --test", diff --git a/scripts/build-android.sh b/scripts/build-android.sh index 874761ce..ba4d3ac6 100755 --- a/scripts/build-android.sh +++ b/scripts/build-android.sh @@ -193,9 +193,9 @@ if [ "$BUILD_MODE" = "development" ]; then export VITE_DEFAULT_ENDORSER_API_SERVER="http://${CUSTOM_API_IP}:3000" log_info "Android development mode: Using custom IP ${CUSTOM_API_IP} for physical device" else - # Use default emulator IP (10.0.2.2) for Android development + # Use Android emulator IP (10.0.2.2) for Android development export VITE_DEFAULT_ENDORSER_API_SERVER="http://10.0.2.2:3000" - log_debug "Android development mode: Using default 10.0.2.2 for emulator" + 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 985fb080..33e78e3b 100755 --- a/scripts/build-ios.sh +++ b/scripts/build-ios.sh @@ -22,6 +22,7 @@ SYNC_ONLY=false ASSETS_ONLY=false DEPLOY_APP=false AUTO_RUN=false +CUSTOM_API_IP="" # Function to print iOS-specific usage print_ios_usage() { @@ -41,6 +42,7 @@ print_ios_usage() { echo " --assets Generate assets only" echo " --deploy Deploy app to connected device" echo " --auto-run Auto-run app after build" + echo " --api-ip Custom IP address for claim API (uses Capacitor default)" echo "" echo "Common Options:" echo " -h, --help Show this help message" @@ -54,12 +56,19 @@ print_ios_usage() { echo " $0 --clean # Clean only" echo " $0 --sync # Sync only" echo " $0 --deploy # Build and deploy to device" + echo " $0 --dev # Dev build with Capacitor default" + echo " $0 --dev --api-ip 192.168.1.100 # Dev build with custom API IP" echo "" } # Function to parse iOS-specific arguments parse_ios_args() { - for arg in "$@"; do + local args=("$@") + local i=0 + + while [ $i -lt ${#args[@]} ]; do + local arg="${args[$i]}" + case $arg in --dev|--development) BUILD_MODE="development" @@ -100,6 +109,18 @@ parse_ios_args() { --auto-run) AUTO_RUN=true ;; + --api-ip) + if [ $((i + 1)) -lt ${#args[@]} ]; then + CUSTOM_API_IP="${args[$((i + 1))]}" + i=$((i + 1)) # Skip the next argument + else + log_error "Error: --api-ip requires an IP address" + exit 1 + fi + ;; + --api-ip=*) + CUSTOM_API_IP="${arg#*=}" + ;; -h|--help) print_ios_usage exit 0 @@ -111,6 +132,7 @@ parse_ios_args() { log_warn "Unknown argument: $arg" ;; esac + i=$((i + 1)) done } @@ -291,6 +313,13 @@ 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 +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" + log_info "iOS development mode: Using custom IP ${CUSTOM_API_IP} for physical device" +fi + # Setup application directories setup_app_directories From 974d33b32269eefa4472960c5b4dd1788674f957 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 5 Aug 2025 11:51:48 +0000 Subject: [PATCH 05/10] 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 From b17642fbcb77ede17b1c174ee76e3232affe7226 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Tue, 5 Aug 2025 19:58:39 -0600 Subject: [PATCH 06/10] fix: Toast messages were showing numbers. Removed unused function. Clarified tests. --- src/test/PlatformServiceMixinTest.vue | 6 +++--- src/views/ContactQRScanShowView.vue | 3 ++- src/views/GiftedDetailsView.vue | 3 ++- src/views/HomeView.vue | 11 ----------- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/test/PlatformServiceMixinTest.vue b/src/test/PlatformServiceMixinTest.vue index 3f635f71..f54eea11 100644 --- a/src/test/PlatformServiceMixinTest.vue +++ b/src/test/PlatformServiceMixinTest.vue @@ -11,7 +11,7 @@ class="px-4 py-2 rounded mr-2 transition-colors" @click="testInsert" > - Test Insert + Test Contact Insert