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/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/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' 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/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 new file mode 100644 index 00000000..0d2eadee --- /dev/null +++ b/docs/build-system/platforms/android-custom-api-ip.md @@ -0,0 +1,322 @@ +# Mobile 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 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 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 +# Android - Default behavior (uses 10.0.2.2 for emulator) +./scripts/build-android.sh --dev + +# 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 +# Android - Default development build (uses 10.0.2.2 for emulator) +npm run build:android:dev + +# Android - Development build with custom IP (requires IP parameter) +npm run build:android:dev:custom 192.168.1.100 + +# 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 Simulator/Emulator (Default) + +```bash +# Android - Default behavior - uses 10.0.2.2 for emulator +npm run build:android:dev + +# 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 + +```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 + +```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 (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-ios.sh --dev --api-ip 192.168.1.100 --studio +``` + +## How It Works + +### Environment Variable Override + +The build system handles API server configuration as follows: + +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 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 +``` + +### Default Behavior + +- **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 + +## 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..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", @@ -104,7 +108,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 bf3df09a..53ada97e 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,6 +186,21 @@ log_info "Build type: $BUILD_TYPE" # Setup environment for Capacitor build setup_build_env "capacitor" +# 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 + # Setup application directories setup_app_directories diff --git a/scripts/build-ios.sh b/scripts/build-ios.sh index 985fb080..9c3b2118 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,14 @@ log_info "Build type: $BUILD_TYPE" # Setup environment for Capacitor build setup_build_env "capacitor" +# 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 + # Setup application directories setup_app_directories diff --git a/scripts/common.sh b/scripts/common.sh index cb658998..eb5956b6 100755 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -51,10 +51,18 @@ log_step() { # Function to measure and log execution time measure_time() { local start_time=$(date +%s) - "$@" - local end_time=$(date +%s) - local duration=$((end_time - start_time)) - log_success "Completed in ${duration} seconds" + if "$@"; then + local end_time=$(date +%s) + local duration=$((end_time - start_time)) + log_success "Completed in ${duration} seconds" + return 0 + else + local exit_code=$? + local end_time=$(date +%s) + local duration=$((end_time - start_time)) + log_error "Failed after ${duration} seconds (exit code: ${exit_code})" + return $exit_code + fi } # Function to print section headers @@ -197,20 +205,22 @@ 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" + 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" - 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_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 diff --git a/src/libs/util.ts b/src/libs/util.ts index 3404054d..ae056fe6 100644 --- a/src/libs/util.ts +++ b/src/libs/util.ts @@ -35,17 +35,6 @@ import { IIdentifier } from "@veramo/core"; import { DEFAULT_ROOT_DERIVATION_PATH } from "./crypto"; // Consolidate this with src/utils/PlatformServiceMixin._parseJsonField -function parseJsonField(value: unknown, defaultValue: T): T { - if (typeof value === "string") { - try { - return JSON.parse(value); - } catch { - return defaultValue; - } - } - return (value as T) || defaultValue; -} - function mapQueryResultToValues( record: { columns: string[]; values: unknown[][] } | undefined, ): Array> { @@ -806,7 +795,7 @@ export const contactToCsvLine = (contact: Contact): string => { // Handle contactMethods array by stringifying it const contactMethodsStr = contact.contactMethods - ? escapeField(JSON.stringify(parseJsonField(contact.contactMethods, []))) + ? escapeField(JSON.stringify(contact.contactMethods)) : ""; const fields = [ @@ -918,7 +907,7 @@ export const contactsToExportJson = (contacts: Contact[]): DatabaseExport => { contact, ); exContact.contactMethods = contact.contactMethods - ? JSON.stringify(parseJsonField(contact.contactMethods, [])) + ? JSON.stringify(contact.contactMethods) : undefined; return exContact; }); 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