fix(ios): configure method parameter parsing and improve build process

Fix configure() method to read parameters directly from CAPPluginCall
instead of expecting nested options object, matching Android implementation.

Improve build process to ensure canonical UI is always copied:
- iOS build script: Copy www/index.html to test app before build
- Android build.gradle: Add copyCanonicalUI task to run before build
- Ensures test apps always use latest UI from www/index.html

This fixes the issue where configure() was returning 'Configuration
options required' error because it expected a nested options object
when Capacitor passes parameters directly on the call object.
This commit is contained in:
Matthew
2025-11-19 20:09:01 -08:00
parent 3d9254e26d
commit 92bb566631
5 changed files with 822 additions and 1149 deletions

View File

@@ -126,6 +126,9 @@ fi
build_ios_test_app() {
log_step "Building iOS test app..."
# Get repo root before changing directories (we're currently in repo root from main())
REPO_ROOT="$(pwd)"
# Navigate to iOS App directory (where workspace is located)
IOS_APP_DIR="$TEST_APP_DIR/ios/App"
if [ ! -d "$IOS_APP_DIR" ]; then
@@ -162,6 +165,61 @@ build_ios_test_app() {
log_warn "No Podfile found, skipping pod install"
fi
# Copy canonical UI from www/index.html to test app
log_step "Copying canonical UI from www/index.html..."
# Use REPO_ROOT calculated before changing directories
CANONICAL_UI="$REPO_ROOT/www/index.html"
IOS_UI_SOURCE="$REPO_ROOT/$TEST_APP_DIR/App/App/Public/index.html"
IOS_UI_RUNTIME="$REPO_ROOT/$TEST_APP_DIR/ios/App/App/public/index.html"
if [ -f "$CANONICAL_UI" ]; then
# Copy to source location (for Capacitor sync)
if cp "$CANONICAL_UI" "$IOS_UI_SOURCE"; then
log_info "Copied canonical UI to iOS test app source"
else
log_error "Failed to copy canonical UI to source"
exit 1
fi
# Also copy directly to runtime location (in case sync doesn't run or is cached)
if [ -d "$(dirname "$IOS_UI_RUNTIME")" ]; then
if cp "$CANONICAL_UI" "$IOS_UI_RUNTIME"; then
log_info "Copied canonical UI to iOS test app runtime"
else
log_warn "Failed to copy canonical UI to runtime (may be synced later)"
fi
else
log_warn "Runtime directory not found, will be created by Capacitor sync"
fi
else
log_warn "Canonical UI not found at $CANONICAL_UI, skipping copy"
fi
# Sync Capacitor from test app root (where capacitor.config.json is located)
# This must run from test-apps/ios-test-app, not from ios/App/App
log_step "Syncing Capacitor..."
TEST_APP_ROOT="$REPO_ROOT/$TEST_APP_DIR"
if [ -f "$TEST_APP_ROOT/capacitor.config.json" ] || [ -f "$TEST_APP_ROOT/capacitor.config.ts" ]; then
if command -v npx &> /dev/null; then
# Save current directory
CURRENT_DIR="$(pwd)"
# Change to test app root for sync
cd "$TEST_APP_ROOT" || exit 1
if ! npx cap sync ios; then
log_error "Capacitor sync failed"
cd "$CURRENT_DIR" || exit 1
exit 1
fi
# Return to ios/App directory
cd "$CURRENT_DIR" || exit 1
log_info "Capacitor synced"
else
log_warn "npx not found, skipping Capacitor sync"
fi
else
log_warn "Capacitor config not found at $TEST_APP_ROOT, skipping sync"
fi
# Build TypeScript/JavaScript if package.json exists
if [ -f "package.json" ]; then
log_step "Building web assets..."
@@ -172,32 +230,6 @@ build_ios_test_app() {
fi
log_info "Web assets built"
fi
# Sync Capacitor if needed
# Check for config in current directory or App subdirectory
CAP_CONFIG_DIR=""
if [ -f "capacitor.config.ts" ] || [ -f "capacitor.config.json" ]; then
CAP_CONFIG_DIR="."
elif [ -f "App/capacitor.config.json" ] || [ -f "App/capacitor.config.ts" ]; then
CAP_CONFIG_DIR="App"
fi
if command -v npx &> /dev/null && [ -n "$CAP_CONFIG_DIR" ]; then
log_step "Syncing Capacitor..."
# Run sync from directory containing config
if [ "$CAP_CONFIG_DIR" != "." ]; then
cd "$CAP_CONFIG_DIR" || exit 1
fi
if ! npx cap sync ios; then
log_error "Capacitor sync failed"
exit 1
fi
# Return to ios/App directory if we changed
if [ "$CAP_CONFIG_DIR" != "." ]; then
cd .. || exit 1
fi
log_info "Capacitor synced"
fi
fi
# Determine SDK and destination
@@ -244,7 +276,16 @@ build_ios_test_app() {
ARCHIVE_PATH="build/ios-test-app-device.xcarchive"
fi
# Clean build folder
# Ensure UI is copied to runtime location one more time before build
# (in case sync didn't run or was cached)
log_step "Ensuring canonical UI is in runtime location before build..."
if [ -f "$CANONICAL_UI" ] && [ -d "$(dirname "$IOS_UI_RUNTIME")" ]; then
if cp "$CANONICAL_UI" "$IOS_UI_RUNTIME"; then
log_info "Canonical UI copied to runtime location (pre-build)"
fi
fi
# Clean build folder (removes old DerivedData)
log_step "Cleaning build folder..."
if [ -n "$WORKSPACE" ]; then
xcodebuild clean -workspace "$WORKSPACE" -scheme "$SCHEME" -configuration "$BUILD_CONFIG" -sdk "$SDK" || true
@@ -252,6 +293,15 @@ build_ios_test_app() {
xcodebuild clean -project "$PROJECT" -scheme "$SCHEME" -configuration "$BUILD_CONFIG" -sdk "$SDK" || true
fi
# Also clean DerivedData for this specific project to remove cached HTML
log_step "Cleaning DerivedData for fresh build..."
DERIVED_DATA_PATH="$HOME/Library/Developer/Xcode/DerivedData"
if [ -d "$DERIVED_DATA_PATH" ]; then
# Find and remove DerivedData folders for this project
find "$DERIVED_DATA_PATH" -maxdepth 1 -type d -name "App-*" -exec rm -rf {} \; 2>/dev/null || true
log_info "DerivedData cleaned"
fi
# Build
log_step "Building for $TARGET ($BUILD_CONFIG)..."
if [ -n "$WORKSPACE" ]; then
@@ -292,6 +342,17 @@ build_ios_test_app() {
if [ -n "$APP_PATH" ]; then
log_info "App built at: $APP_PATH"
# Force copy canonical UI directly into built app bundle (ensures latest version)
log_step "Copying canonical UI into built app bundle..."
BUILT_APP_HTML="$APP_PATH/public/index.html"
if [ -f "$CANONICAL_UI" ] && [ -d "$(dirname "$BUILT_APP_HTML")" ]; then
if cp "$CANONICAL_UI" "$BUILT_APP_HTML"; then
log_info "✅ Canonical UI copied directly into app bundle"
else
log_warn "Failed to copy UI into app bundle (may use cached version)"
fi
fi
log_info ""
# Boot simulator if not already booted
@@ -363,6 +424,19 @@ build_ios_test_app() {
fi
fi
# Uninstall existing app (if present) to ensure clean install
log_step "Uninstalling existing app (if present)..."
APP_BUNDLE_ID="com.timesafari.dailynotification.test"
if xcrun simctl uninstall "$SIMULATOR_ID" "$APP_BUNDLE_ID" 2>&1; then
log_info "Existing app uninstalled"
else
# App may not be installed, which is fine
log_info "No existing app to uninstall (or uninstall failed - continuing anyway)"
fi
# Wait a moment after uninstall
sleep 1
# Install the app
log_step "Installing app on simulator..."
if xcrun simctl install "$SIMULATOR_ID" "$APP_PATH" 2>&1; then
@@ -383,9 +457,9 @@ build_ios_test_app() {
sleep 2
# Method 1: Direct launch (capture output to check for errors)
# Note: Bundle ID is com.timesafari.dailynotification (not .test)
# Note: Bundle ID is com.timesafari.dailynotification.test
log_info "Attempting to launch app..."
LAUNCH_OUTPUT=$(xcrun simctl launch "$SIMULATOR_ID" com.timesafari.dailynotification 2>&1)
LAUNCH_OUTPUT=$(xcrun simctl launch "$SIMULATOR_ID" "$APP_BUNDLE_ID" 2>&1)
LAUNCH_EXIT_CODE=$?
if [ $LAUNCH_EXIT_CODE -eq 0 ]; then
@@ -410,19 +484,19 @@ build_ios_test_app() {
if [ "$LAUNCH_SUCCESS" = false ]; then
log_info "Checking if app is already running..."
sleep 2
RUNNING_APPS=$(xcrun simctl listapps "$SIMULATOR_ID" 2>/dev/null | grep -A 5 "com.timesafari.dailynotification" || echo "")
RUNNING_APPS=$(xcrun simctl listapps "$SIMULATOR_ID" 2>/dev/null | grep -A 5 "$APP_BUNDLE_ID" || echo "")
if [ -n "$RUNNING_APPS" ]; then
log_info "App appears to be installed. Trying to verify it's running..."
# Try to get app state
APP_STATE=$(xcrun simctl listapps "$SIMULATOR_ID" 2>/dev/null | grep -A 10 "com.timesafari.dailynotification" | grep "ApplicationType" || echo "")
APP_STATE=$(xcrun simctl listapps "$SIMULATOR_ID" 2>/dev/null | grep -A 10 "$APP_BUNDLE_ID" | grep "ApplicationType" || echo "")
if [ -n "$APP_STATE" ]; then
log_info "App found in simulator. Attempting manual launch..."
# Try opening via Simulator app
open -a Simulator
sleep 1
# Try launch one more time
if xcrun simctl launch "$SIMULATOR_ID" com.timesafari.dailynotification >/dev/null 2>&1; then
if xcrun simctl launch "$SIMULATOR_ID" "$APP_BUNDLE_ID" >/dev/null 2>&1; then
LAUNCH_SUCCESS=true
log_info "✅ App launched successfully on retry!"
fi
@@ -434,7 +508,7 @@ build_ios_test_app() {
if [ "$LAUNCH_SUCCESS" = true ]; then
sleep 2
# Try to verify app is running by checking if we can get its container
if xcrun simctl get_app_container "$SIMULATOR_ID" com.timesafari.dailynotification >/dev/null 2>&1; then
if xcrun simctl get_app_container "$SIMULATOR_ID" "$APP_BUNDLE_ID" >/dev/null 2>&1; then
log_info "✅ Verified: App is installed and accessible"
else
log_warn "⚠️ Launch reported success but app verification failed"
@@ -446,7 +520,7 @@ build_ios_test_app() {
log_info "The app is installed. To launch manually:"
log_info " 1. Open Simulator app (if not already open)"
log_info " 2. Find the app icon on the home screen and tap it"
log_info " 3. Or run: xcrun simctl launch $SIMULATOR_ID com.timesafari.dailynotification"
log_info " 3. Or run: xcrun simctl launch $SIMULATOR_ID $APP_BUNDLE_ID"
if [ -n "$LAUNCH_ERROR" ]; then
log_info ""
log_info "Launch error details:"
@@ -460,7 +534,7 @@ build_ios_test_app() {
log_info ""
log_info "To run on simulator manually:"
log_info " xcrun simctl install booted \"$APP_PATH\""
log_info " xcrun simctl launch booted com.timesafari.dailynotification"
log_info " xcrun simctl launch booted com.timesafari.dailynotification.test"
fi
else
log_warn "Could not find built app in DerivedData"