feat(docs): P3.4-A/B Documentation polish - JSDoc and troubleshooting
P3.4-A: Enhanced public API JSDoc - Enhanced createSchedule() with detailed parameter docs and examples - Enhanced updateSchedule() with examples and error documentation - Enhanced deleteSchedule() with error documentation - Enhanced enableSchedule() with examples P3.4-B: Created troubleshooting guide - docs/TROUBLESHOOTING.md with common issues and solutions - Covers CI failures, packaging, platform tests, build, permissions, recovery, performance - Linked in docs/00-INDEX.md Verification: - TypeScript compiles ✅ - JSDoc generates in .d.ts files ✅ - Documentation created and linked ✅
This commit is contained in:
@@ -19,6 +19,7 @@ These are **policy-as-code**. Any gate (push, release, publish) MUST call `./ci/
|
||||
- **Verification / Invariants:** `./scripts/verify.sh` — Encodes packaging, core-purity, and build invariants
|
||||
- **CI Usage & Setup:** `ci/README.md` — Local CI documentation
|
||||
- **Performance Characteristics:** `docs/PERFORMANCE.md` — Performance characteristics and benchmarks
|
||||
- **Troubleshooting Guide:** `docs/TROUBLESHOOTING.md` — Common issues and solutions
|
||||
|
||||
---
|
||||
|
||||
|
||||
151
docs/TROUBLESHOOTING.md
Normal file
151
docs/TROUBLESHOOTING.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# Troubleshooting Guide
|
||||
|
||||
**Purpose:** Common issues, symptoms, causes, and solutions.
|
||||
**Owner:** Development Team
|
||||
**Last Updated:** 2025-12-22
|
||||
**Status:** active
|
||||
|
||||
---
|
||||
|
||||
## CI Failures
|
||||
|
||||
### Symptom: `./ci/run.sh` fails
|
||||
|
||||
**Causes:**
|
||||
- Forbidden files in package
|
||||
- Core module imports platform deps
|
||||
- Export paths don't match artifacts
|
||||
|
||||
**Solutions:**
|
||||
1. Check forbidden files: `npm pack --dry-run | grep -E "xcuserdata|xcuserstate|DerivedData|ios/App/"`
|
||||
2. Check core purity: `grep -r "@capacitor\|react\|fs\|path\|os" src/core/`
|
||||
3. Check exports: `node -e "const p=require('./package.json'); console.log(JSON.stringify(p.exports, null, 2))"`
|
||||
|
||||
---
|
||||
|
||||
## Packaging Failures
|
||||
|
||||
### Symptom: `npm pack` includes forbidden files
|
||||
|
||||
**Causes:**
|
||||
- `package.json` `files` field is too permissive
|
||||
- `.npmignore` is missing or incomplete
|
||||
|
||||
**Solutions:**
|
||||
1. Review `package.json` `files` field (should be whitelist)
|
||||
2. Add to `.npmignore`: `**/xcuserdata/`, `**/*.xcuserstate`, `**/DerivedData/`, `ios/App/`, `.DS_Store`
|
||||
3. Run `npm pack --dry-run` to verify
|
||||
|
||||
---
|
||||
|
||||
## Platform Test Failures
|
||||
|
||||
### Symptom: Android tests fail in CI
|
||||
|
||||
**Causes:**
|
||||
- Robolectric SDK version mismatch
|
||||
- Missing test dependencies
|
||||
- Test database setup issues
|
||||
|
||||
**Solutions:**
|
||||
1. Check `@Config(sdk = [34])` matches Robolectric version
|
||||
2. Verify `android/build.gradle` has test dependencies
|
||||
3. Check `TestDBFactory` creates in-memory database correctly
|
||||
|
||||
### Symptom: iOS tests not running in CI
|
||||
|
||||
**Causes:**
|
||||
- macOS runner not available
|
||||
- xcodebuild not found
|
||||
- Test app not configured
|
||||
|
||||
**Solutions:**
|
||||
1. Use scheduled/manual workflows for iOS tests
|
||||
2. Verify `xcodebuild` is available: `xcodebuild -version`
|
||||
3. Check test app configuration in `test-apps/ios-test-app/`
|
||||
|
||||
---
|
||||
|
||||
## Build Failures
|
||||
|
||||
### Symptom: TypeScript compilation fails
|
||||
|
||||
**Causes:**
|
||||
- Type errors in source code
|
||||
- Missing type definitions
|
||||
- Incorrect import paths
|
||||
|
||||
**Solutions:**
|
||||
1. Run `npx tsc --noEmit` to see all type errors
|
||||
2. Check import paths match `package.json` exports
|
||||
3. Verify all dependencies are installed: `npm install`
|
||||
|
||||
### Symptom: Build succeeds but runtime errors occur
|
||||
|
||||
**Causes:**
|
||||
- Missing runtime dependencies
|
||||
- Incorrect module resolution
|
||||
- Platform-specific code not available
|
||||
|
||||
**Solutions:**
|
||||
1. Check `dist/` directory contains expected files
|
||||
2. Verify `package.json` exports match build artifacts
|
||||
3. Test on actual platform (not just build)
|
||||
|
||||
---
|
||||
|
||||
## Permission Issues
|
||||
|
||||
### Symptom: Notifications not appearing
|
||||
|
||||
**Causes:**
|
||||
- Permission not granted
|
||||
- Battery optimization killing background tasks
|
||||
- Platform-specific permission issues
|
||||
|
||||
**Solutions:**
|
||||
1. Check permission status: `await DailyNotification.checkPermission()`
|
||||
2. Request permission: `await DailyNotification.requestPermission()`
|
||||
3. Check battery optimization settings (Android)
|
||||
4. Verify Info.plist/AndroidManifest.xml permissions
|
||||
|
||||
---
|
||||
|
||||
## Recovery Issues
|
||||
|
||||
### Symptom: Missed notifications after app restart
|
||||
|
||||
**Causes:**
|
||||
- Recovery not running on app launch
|
||||
- Database corruption
|
||||
- Platform-specific recovery limitations
|
||||
|
||||
**Solutions:**
|
||||
1. Check recovery logs in history: `await DailyNotification.getHistory({ kind: 'recovery' })`
|
||||
2. Verify recovery is called on app launch
|
||||
3. Check database integrity
|
||||
4. Review platform-specific recovery constraints
|
||||
|
||||
---
|
||||
|
||||
## Performance Issues
|
||||
|
||||
### Symptom: Slow database queries
|
||||
|
||||
**Causes:**
|
||||
- Large number of schedules
|
||||
- Missing database indexes
|
||||
- Database corruption
|
||||
|
||||
**Solutions:**
|
||||
1. Check query performance in logs (warnings if > 100ms)
|
||||
2. Review database schema for missing indexes
|
||||
3. Consider database cleanup/migration
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
- [SYSTEM_INVARIANTS.md](./SYSTEM_INVARIANTS.md) — Enforced system invariants
|
||||
- [PERFORMANCE.md](./PERFORMANCE.md) — Performance characteristics
|
||||
- [docs/progress/03-TEST-RUNS.md](./progress/03-TEST-RUNS.md) — Test run history
|
||||
|
||||
@@ -610,13 +610,33 @@ export interface DailyNotificationPlugin {
|
||||
* Create a new recurring schedule
|
||||
*
|
||||
* @param schedule Schedule configuration
|
||||
* @param schedule.id - Unique schedule identifier (required, must be unique)
|
||||
* @param schedule.kind - Schedule type: 'notify' for notifications, 'fetch' for content fetching
|
||||
* @param schedule.cron - Cron expression (e.g., '0 9 * * *' for daily at 9 AM). Mutually exclusive with clockTime
|
||||
* @param schedule.clockTime - Time of day in HH:mm format (e.g., '09:00'). Mutually exclusive with cron
|
||||
* @param schedule.enabled - Whether schedule is active (default: true)
|
||||
* @param schedule.jitterMs - Random jitter in milliseconds (default: 0)
|
||||
* @param schedule.backoffPolicy - Backoff policy for retries (default: 'exp')
|
||||
* @returns Promise resolving to created Schedule object
|
||||
* @throws {DailyNotificationError} If schedule creation fails (e.g., invalid cron, duplicate ID, permission denied)
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const schedule = await DailyNotification.createSchedule({
|
||||
* id: 'morning-notification',
|
||||
* kind: 'notify',
|
||||
* cron: '0 9 * * *', // Daily at 9 AM
|
||||
* clockTime: '09:00',
|
||||
* enabled: true
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Using cron expression
|
||||
* const schedule = await DailyNotification.createSchedule({
|
||||
* id: 'daily-fetch',
|
||||
* kind: 'fetch',
|
||||
* cron: '0 */6 * * *', // Every 6 hours
|
||||
* enabled: true
|
||||
* });
|
||||
* ```
|
||||
@@ -626,26 +646,59 @@ export interface DailyNotificationPlugin {
|
||||
/**
|
||||
* Update an existing schedule
|
||||
*
|
||||
* @param id Schedule ID
|
||||
* @param updates Partial schedule updates
|
||||
* @param id Schedule ID (required)
|
||||
* @param updates Partial schedule updates. Only provided fields will be updated.
|
||||
* @returns Promise resolving to updated Schedule object
|
||||
* @throws {DailyNotificationError} If schedule not found, invalid updates, or permission denied
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Update schedule time
|
||||
* const updated = await DailyNotification.updateSchedule('morning-notification', {
|
||||
* clockTime: '10:00'
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Disable a schedule
|
||||
* await DailyNotification.updateSchedule('morning-notification', {
|
||||
* enabled: false
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
updateSchedule(id: string, updates: Partial<Schedule>): Promise<Schedule>;
|
||||
|
||||
/**
|
||||
* Delete a schedule
|
||||
*
|
||||
* @param id Schedule ID
|
||||
* @param id Schedule ID (required)
|
||||
* @returns Promise resolving when deletion completes
|
||||
* @throws {DailyNotificationError} If schedule not found or deletion fails
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await DailyNotification.deleteSchedule('morning-notification');
|
||||
* ```
|
||||
*/
|
||||
deleteSchedule(id: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Enable or disable a schedule
|
||||
*
|
||||
* @param id Schedule ID
|
||||
* @param enabled Enable state
|
||||
* @param id Schedule ID (required)
|
||||
* @param enabled Enable state (true to enable, false to disable)
|
||||
* @returns Promise resolving when update completes
|
||||
* @throws {DailyNotificationError} If schedule not found or update fails
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Enable a schedule
|
||||
* await DailyNotification.enableSchedule('morning-notification', true);
|
||||
*
|
||||
* // Disable a schedule
|
||||
* await DailyNotification.enableSchedule('morning-notification', false);
|
||||
* ```
|
||||
*/
|
||||
enableSchedule(id: string, enabled: boolean): Promise<void>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user