From 8191fb07db2152714bc45612b1e66429d19c3864 Mon Sep 17 00:00:00 2001 From: Jose Olarte III Date: Fri, 19 Dec 2025 12:54:49 +0800 Subject: [PATCH] fix(test-app): Fix iOS build issues and TypeScript errors Fix multiple issues preventing iOS builds and TypeScript compilation: - Fix postinstall script to handle missing directories gracefully - Create assets directory if it doesn't exist before writing capacitor.plugins.json - Don't exit on error if Capacitor hasn't synced yet (allows npm install to succeed) - Fix TypeScript compilation errors - Add optional fields to PermissionStatus interface (exactAlarmEnabled, wakeLockEnabled, allPermissionsGranted) - Fix type assertion in HomeView.vue to use 'as any' for dynamic plugin methods - Fix Podfile configuration issues - Update fix script to detect correct pod path (node_modules vs file dependency) - Fix pod name from TimesafariDailyNotificationPlugin to DailyNotificationPlugin - Handle both node_modules and relative paths for file dependencies - Update iOS sync workflow - Add fix script to cap:sync:ios (runs before and after sync) - Automatically run pod install after fixing Podfile - Handle cap sync failures gracefully with || true - Update documentation - Reflect that iOS sync now includes fix script - Note that pod install is handled automatically - Update troubleshooting section for Podfile errors Fixes: - npm install failing due to missing assets directory - TypeScript build errors in typed-plugin.ts and HomeView.vue - iOS pod install failing with "No podspec found for TimesafariDailyNotificationPlugin" - Capacitor sync overwriting Podfile with incorrect pod name --- .../docs/BUILD_QUICK_REFERENCE.md | 16 ++++++++----- .../daily-notification-test/ios/App/Podfile | 6 ++--- .../daily-notification-test/package-lock.json | 24 +++++++++++++++++++ .../daily-notification-test/package.json | 2 +- .../scripts/fix-capacitor-plugins.js | 24 ++++++++++++++----- .../daily-notification-test/src/lib/bridge.ts | 3 +++ .../src/views/HomeView.vue | 4 ++-- 7 files changed, 61 insertions(+), 18 deletions(-) diff --git a/test-apps/daily-notification-test/docs/BUILD_QUICK_REFERENCE.md b/test-apps/daily-notification-test/docs/BUILD_QUICK_REFERENCE.md index ff05319..4bee087 100644 --- a/test-apps/daily-notification-test/docs/BUILD_QUICK_REFERENCE.md +++ b/test-apps/daily-notification-test/docs/BUILD_QUICK_REFERENCE.md @@ -110,16 +110,20 @@ npx cap run ios ## âš ī¸ Why `npm run cap:sync` is Important -**Problem**: `npx cap sync` overwrites `capacitor.plugins.json` and `capacitor.settings.gradle` with incorrect paths. +**Problem**: `npx cap sync` overwrites configuration files with incorrect paths: +- `capacitor.plugins.json` - Plugin registry gets cleared +- `capacitor.settings.gradle` - Android plugin path is wrong +- `ios/App/Podfile` - iOS pod name is wrong (`TimesafariDailyNotificationPlugin` instead of `DailyNotificationPlugin`) **Solution**: The `cap:sync` script automatically: 1. Runs `npx cap sync` (syncs both Android and iOS) -2. Fixes `capacitor.settings.gradle` (corrects plugin path from `android/` to `android/plugin/`) +2. Fixes `capacitor.settings.gradle` (corrects plugin path from `android/plugin/` to `android/`) 3. Restores the DailyNotification plugin entry in `capacitor.plugins.json` +4. Fixes `ios/App/Podfile` (corrects pod name and path) **Platform-specific sync:** - `npm run cap:sync:android` - Syncs Android only (includes fix script) -- `npm run cap:sync:ios` - Syncs iOS only (no fix needed for iOS) +- `npm run cap:sync:ios` - Syncs iOS only (includes fix script and runs `pod install`) **Without the fix**: Plugin detection fails, build errors occur, "simplified dialog" appears. @@ -326,8 +330,8 @@ xcrun simctl spawn booted log stream | grep -i "dailynotification\|capacitor\|pl ## 📝 Important Notes **Remember**: -- Use `npm run cap:sync` to sync both platforms (automatically fixes Android configuration files) +- Use `npm run cap:sync` to sync both platforms (automatically fixes configuration files) - Use `npm run cap:sync:android` for Android-only sync (includes fix script) -- Use `npm run cap:sync:ios` for iOS-only sync +- Use `npm run cap:sync:ios` for iOS-only sync (includes fix script and automatically runs `pod install`) - Always run `npm run build` before syncing to ensure latest web assets are copied -- For iOS: Run `pod install` in `ios/App/` after first sync or when dependencies change +- The iOS sync script handles `pod install` automatically, but you can run it manually in `ios/App/` if needed diff --git a/test-apps/daily-notification-test/ios/App/Podfile b/test-apps/daily-notification-test/ios/App/Podfile index bf7e1a8..e9d90b2 100644 --- a/test-apps/daily-notification-test/ios/App/Podfile +++ b/test-apps/daily-notification-test/ios/App/Podfile @@ -1,4 +1,4 @@ -require_relative '../../../../node_modules/@capacitor/ios/scripts/pods_helpers' +require_relative '../../node_modules/@capacitor/ios/scripts/pods_helpers' platform :ios, '13.0' use_frameworks! @@ -9,8 +9,8 @@ use_frameworks! install! 'cocoapods', :disable_input_output_paths => true def capacitor_pods - pod 'Capacitor', :path => '../../../../node_modules/@capacitor/ios' - pod 'CapacitorCordova', :path => '../../../../node_modules/@capacitor/ios' + pod 'Capacitor', :path => '../../node_modules/@capacitor/ios' + pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios' pod 'DailyNotificationPlugin', :path => '../../node_modules/@timesafari/daily-notification-plugin/ios' end diff --git a/test-apps/daily-notification-test/package-lock.json b/test-apps/daily-notification-test/package-lock.json index 6b09a41..a6db6d6 100644 --- a/test-apps/daily-notification-test/package-lock.json +++ b/test-apps/daily-notification-test/package-lock.json @@ -12,6 +12,7 @@ "@capacitor/android": "^6.2.1", "@capacitor/cli": "^6.2.1", "@capacitor/core": "^6.2.1", + "@capacitor/ios": "^6.2.1", "@timesafari/daily-notification-plugin": "file:../../", "date-fns": "^4.1.0", "did-jwt": "^7.4.7", @@ -117,6 +118,7 @@ "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -416,6 +418,7 @@ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", "license": "MIT", + "peer": true, "dependencies": { "@babel/types": "^7.28.4" }, @@ -634,10 +637,20 @@ "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-6.2.1.tgz", "integrity": "sha512-urZwxa7hVE/BnA18oCFAdizXPse6fCKanQyEqpmz6cBJ2vObwMpyJDG5jBeoSsgocS9+Ax+9vb4ducWJn0y2qQ==", "license": "MIT", + "peer": true, "dependencies": { "tslib": "^2.1.0" } }, + "node_modules/@capacitor/ios": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@capacitor/ios/-/ios-6.2.1.tgz", + "integrity": "sha512-tbMlQdQjxe1wyaBvYVU1yTojKJjgluZQsJkALuJxv/6F8QTw5b6vd7X785O/O7cMpIAZfUWo/vtAHzFkRV+kXw==", + "license": "MIT", + "peerDependencies": { + "@capacitor/core": "^6.2.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.11", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.11.tgz", @@ -2065,6 +2078,7 @@ "integrity": "sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.1", "@typescript-eslint/types": "8.46.1", @@ -2663,6 +2677,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2911,6 +2926,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -3373,6 +3389,7 @@ "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -3434,6 +3451,7 @@ "integrity": "sha512-K6tP0dW8FJVZLQxa2S7LcE1lLw3X8VvB3t887Q6CLrFVxHYBXGANbXvwNzYIu6Ughx1bSJ5BDT0YB3ybPT39lw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "natural-compare": "^1.4.0", @@ -4293,6 +4311,7 @@ "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "jiti": "lib/jiti-cli.mjs" } @@ -5721,6 +5740,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -5798,6 +5818,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6031,6 +6052,7 @@ "integrity": "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -6301,6 +6323,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -6320,6 +6343,7 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.22.tgz", "integrity": "sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==", "license": "MIT", + "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.22", "@vue/compiler-sfc": "3.5.22", diff --git a/test-apps/daily-notification-test/package.json b/test-apps/daily-notification-test/package.json index 8946f48..6966773 100644 --- a/test-apps/daily-notification-test/package.json +++ b/test-apps/daily-notification-test/package.json @@ -15,7 +15,7 @@ "lint": "eslint . --fix", "cap:sync": "npx cap sync && node scripts/fix-capacitor-plugins.js", "cap:sync:android": "npx cap sync android && node scripts/fix-capacitor-plugins.js", - "cap:sync:ios": "npx cap sync ios", + "cap:sync:ios": "node scripts/fix-capacitor-plugins.js && (npx cap sync ios || true) && node scripts/fix-capacitor-plugins.js && cd ios/App && pod install && cd ../..", "postinstall": "node scripts/fix-capacitor-plugins.js" }, "dependencies": { diff --git a/test-apps/daily-notification-test/scripts/fix-capacitor-plugins.js b/test-apps/daily-notification-test/scripts/fix-capacitor-plugins.js index 28ffe17..60d3717 100755 --- a/test-apps/daily-notification-test/scripts/fix-capacitor-plugins.js +++ b/test-apps/daily-notification-test/scripts/fix-capacitor-plugins.js @@ -36,6 +36,13 @@ function fixCapacitorPlugins() { console.log('🔧 Fixing capacitor.plugins.json...'); try { + // Ensure directory exists before writing + const pluginsDir = path.dirname(PLUGINS_JSON_PATH); + if (!fs.existsSync(pluginsDir)) { + fs.mkdirSync(pluginsDir, { recursive: true }); + console.log('â„šī¸ Created assets directory:', pluginsDir); + } + // Read current content let plugins = []; if (fs.existsSync(PLUGINS_JSON_PATH)) { @@ -56,7 +63,8 @@ function fixCapacitorPlugins() { } catch (error) { console.error('❌ Error fixing capacitor.plugins.json:', error.message); - process.exit(1); + // Don't exit on error - this might run before cap sync creates the file + console.log('â„šī¸ This is normal if Capacitor hasn\'t synced yet. Run "npx cap sync android" first.'); } } @@ -119,14 +127,18 @@ function fixPodfile() { let content = fs.readFileSync(PODFILE_PATH, 'utf8'); const originalContent = content; - // The correct pod reference should be: - // pod 'DailyNotificationPlugin', :path => '../../node_modules/@timesafari/daily-notification-plugin/ios' - const correctPodLine = "pod 'DailyNotificationPlugin', :path => '../../node_modules/@timesafari/daily-notification-plugin/ios'"; + // Determine correct path - check if plugin is in node_modules or use relative path for file dependencies + // From ios/App/Podfile: ../../../../ios points to plugin root's ios directory + const nodeModulesPath = '../../node_modules/@timesafari/daily-notification-plugin/ios'; + const relativePath = '../../../../ios'; + const correctPodLine = fs.existsSync(path.join(path.dirname(PODFILE_PATH), nodeModulesPath, 'DailyNotificationPlugin.podspec')) + ? `pod 'DailyNotificationPlugin', :path => '${nodeModulesPath}'` + : `pod 'DailyNotificationPlugin', :path => '${relativePath}'`; // Check if Podfile already has the correct reference if (content.includes("pod 'DailyNotificationPlugin'")) { - // Check if path is correct - if (content.includes('@timesafari/daily-notification-plugin/ios')) { + // Check if path is correct (either node_modules or relative path) + if (content.includes('@timesafari/daily-notification-plugin/ios') || content.includes("'../../../../ios'")) { console.log('✅ Podfile has correct DailyNotificationPlugin reference'); } else { // Fix the path diff --git a/test-apps/daily-notification-test/src/lib/bridge.ts b/test-apps/daily-notification-test/src/lib/bridge.ts index e77583f..06ecd3b 100644 --- a/test-apps/daily-notification-test/src/lib/bridge.ts +++ b/test-apps/daily-notification-test/src/lib/bridge.ts @@ -40,6 +40,9 @@ export interface ScheduleResponse { export interface PermissionStatus { notifications: 'granted' | 'denied' notificationsEnabled: boolean + exactAlarmEnabled?: boolean + wakeLockEnabled?: boolean + allPermissionsGranted?: boolean } export interface NotificationStatus { diff --git a/test-apps/daily-notification-test/src/views/HomeView.vue b/test-apps/daily-notification-test/src/views/HomeView.vue index 448333f..96858ef 100644 --- a/test-apps/daily-notification-test/src/views/HomeView.vue +++ b/test-apps/daily-notification-test/src/views/HomeView.vue @@ -402,9 +402,9 @@ const checkAndRequestPermissions = async (): Promise => { // Request permissions - this will show the iOS system dialog // Try requestNotificationPermissions first (iOS), fallback to requestPermissions if (typeof (plugin as any).requestNotificationPermissions === 'function') { - await (plugin as { requestNotificationPermissions: () => Promise }).requestNotificationPermissions() + await (plugin as any).requestNotificationPermissions() } else if (typeof (plugin as any).requestPermissions === 'function') { - await (plugin as { requestPermissions: () => Promise }).requestPermissions() + await (plugin as any).requestPermissions() } else { throw new Error('Permission request method not available') }