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
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
24
test-apps/daily-notification-test/package-lock.json
generated
24
test-apps/daily-notification-test/package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -40,6 +40,9 @@ export interface ScheduleResponse {
|
||||
export interface PermissionStatus {
|
||||
notifications: 'granted' | 'denied'
|
||||
notificationsEnabled: boolean
|
||||
exactAlarmEnabled?: boolean
|
||||
wakeLockEnabled?: boolean
|
||||
allPermissionsGranted?: boolean
|
||||
}
|
||||
|
||||
export interface NotificationStatus {
|
||||
|
||||
@@ -402,9 +402,9 @@ const checkAndRequestPermissions = async (): Promise<void> => {
|
||||
// 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<void> }).requestNotificationPermissions()
|
||||
await (plugin as any).requestNotificationPermissions()
|
||||
} else if (typeof (plugin as any).requestPermissions === 'function') {
|
||||
await (plugin as { requestPermissions: () => Promise<any> }).requestPermissions()
|
||||
await (plugin as any).requestPermissions()
|
||||
} else {
|
||||
throw new Error('Permission request method not available')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user