# Daily Notification Plugin Migration Guide

**Author**: Matthew Raymer  
**Version**: 2.0.0  
**Created**: 2025-09-22 09:22:32 UTC  
**Last Updated**: 2025-09-22 09:22:32 UTC

## Overview

This migration guide helps you transition from the basic daily notification plugin to the enhanced version with dual scheduling, callback support, and comprehensive observability.

## Breaking Changes

### API Changes

#### New Methods Added

- `scheduleContentFetch()` - Schedule content fetching separately
- `scheduleUserNotification()` - Schedule user notifications separately  
- `scheduleDualNotification()` - Schedule both content fetch and notification
- `getDualScheduleStatus()` - Get comprehensive status information
- `registerCallback()` - Register callback functions
- `unregisterCallback()` - Remove callback functions
- `getRegisteredCallbacks()` - List registered callbacks

#### Enhanced Configuration

- New `DualScheduleConfiguration` interface
- Enhanced `NotificationOptions` with callback support
- New `ContentFetchConfig` and `UserNotificationConfig` interfaces

### Platform Requirements

#### Android

- **Minimum SDK**: API 21 (Android 5.0)
- **Target SDK**: API 34 (Android 14)
- **Permissions**: `POST_NOTIFICATIONS`, `SCHEDULE_EXACT_ALARM`
- **Dependencies**: Room 2.6.1+, WorkManager 2.9.0+

#### iOS  

- **Minimum Version**: iOS 13.0
- **Background Modes**: Background App Refresh, Background Processing
- **Permissions**: Notification permissions required
- **Dependencies**: Core Data, BGTaskScheduler

#### Web

- **Service Worker**: Required for background functionality
- **HTTPS**: Required for Service Worker and push notifications
- **Browser Support**: Chrome 40+, Firefox 44+, Safari 11.1+

## Migration Steps

### Step 1: Update Dependencies

```bash
npm install @timesafari/daily-notification-plugin@^2.1.0
```

### Step 2: Update Import Statements

```typescript
// Before
import { DailyNotification } from '@timesafari/daily-notification-plugin';

// After  
import { 
  DailyNotification,
  DualScheduleConfiguration,
  ContentFetchConfig,
  UserNotificationConfig,
  CallbackEvent
} from '@timesafari/daily-notification-plugin';
```

### Step 3: Update Configuration

#### Basic Migration (Minimal Changes)

```typescript
// Before
await DailyNotification.scheduleDailyNotification({
  title: 'Daily Update',
  body: 'Your daily content is ready',
  schedule: '0 9 * * *'
});

// After (backward compatible)
await DailyNotification.scheduleDailyNotification({
  title: 'Daily Update', 
  body: 'Your daily content is ready',
  schedule: '0 9 * * *'
});
```

#### Enhanced Migration (Recommended)

```typescript
// After (enhanced with dual scheduling)
const config: DualScheduleConfiguration = {
  contentFetch: {
    schedule: '0 8 * * *', // Fetch at 8 AM
    ttlSeconds: 3600,       // 1 hour TTL
    source: 'api',
    url: 'https://api.example.com/daily-content'
  },
  userNotification: {
    schedule: '0 9 * * *',  // Notify at 9 AM
    title: 'Daily Update',
    body: 'Your daily content is ready',
    actions: [
      { id: 'view', title: 'View' },
      { id: 'dismiss', title: 'Dismiss' }
    ]
  }
};

await DailyNotification.scheduleDualNotification(config);
```

### Step 4: Add Callback Support

```typescript
// Register callbacks for external integrations
await DailyNotification.registerCallback('analytics', {
  kind: 'http',
  target: 'https://analytics.example.com/events',
  headers: {
    'Authorization': 'Bearer your-token',
    'Content-Type': 'application/json'
  }
});

await DailyNotification.registerCallback('database', {
  kind: 'local',
  target: 'saveToDatabase'
});

// Local callback function
function saveToDatabase(event: CallbackEvent) {
  console.log('Saving to database:', event);
  // Your database save logic here
}
```

### Step 5: Update Status Monitoring

```typescript
// Before
const status = await DailyNotification.getNotificationStatus();

// After (enhanced status)
const status = await DailyNotification.getDualScheduleStatus();
console.log('Next runs:', status.nextRuns);
console.log('Cache age:', status.cacheAgeMs);
console.log('Circuit breakers:', status.circuitBreakers);
console.log('Performance:', status.performance);
```

## Platform-Specific Migration

### Android Migration

#### Update AndroidManifest.xml

```xml
<!-- Add new permissions -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<!-- Register new receivers -->
<receiver android:name="org.timesafari.dailynotification.NotifyReceiver"
          android:enabled="true"
          android:exported="false" />
<receiver android:name="org.timesafari.dailynotification.BootReceiver"
          android:enabled="true"
          android:exported="false">
  <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
  </intent-filter>
</receiver>
```

#### Update build.gradle

```gradle
dependencies {
    implementation "androidx.room:room-runtime:2.6.1"
    implementation "androidx.work:work-runtime-ktx:2.9.0"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
    annotationProcessor "androidx.room:room-compiler:2.6.1"
}
```

### iOS Migration

#### Update Info.plist

```xml
<key>UIBackgroundModes</key>
<array>
    <string>background-app-refresh</string>
    <string>background-processing</string>
</array>

<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
    <string>org.timesafari.dailynotification.content-fetch</string>
    <string>org.timesafari.dailynotification.notification-delivery</string>
</array>
```

#### Update Capabilities

1. Enable "Background Modes" capability
2. Enable "Background App Refresh"
3. Enable "Background Processing"

### Web Migration

#### Service Worker Registration

```typescript
// Register Service Worker
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(registration => {
      console.log('Service Worker registered:', registration);
    })
    .catch(error => {
      console.error('Service Worker registration failed:', error);
    });
}
```

#### Push Notification Setup

```typescript
// Request notification permission
const permission = await Notification.requestPermission();

if (permission === 'granted') {
  // Subscribe to push notifications
  const subscription = await registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: 'your-vapid-public-key'
  });
  
  // Send subscription to your server
  await fetch('/api/push-subscription', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(subscription)
  });
}
```

## Testing Migration

### Unit Tests

```typescript
import { DailyNotification } from '@timesafari/daily-notification-plugin';

describe('Migration Tests', () => {
  test('backward compatibility', async () => {
    // Test that old API still works
    await DailyNotification.scheduleDailyNotification({
      title: 'Test',
      body: 'Test body',
      schedule: '0 9 * * *'
    });
  });

  test('new dual scheduling', async () => {
    const config = {
      contentFetch: { schedule: '0 8 * * *', ttlSeconds: 3600 },
      userNotification: { schedule: '0 9 * * *', title: 'Test' }
    };
    
    await DailyNotification.scheduleDualNotification(config);
    const status = await DailyNotification.getDualScheduleStatus();
    expect(status.nextRuns).toBeDefined();
  });

  test('callback registration', async () => {
    await DailyNotification.registerCallback('test', {
      kind: 'local',
      target: 'testCallback'
    });
    
    const callbacks = await DailyNotification.getRegisteredCallbacks();
    expect(callbacks).toContain('test');
  });
});
```

### Integration Tests

```typescript
describe('Integration Tests', () => {
  test('end-to-end dual scheduling', async () => {
    // Schedule content fetch
    await DailyNotification.scheduleContentFetch({
      schedule: '0 8 * * *',
      ttlSeconds: 3600,
      source: 'api',
      url: 'https://api.example.com/content'
    });

    // Schedule notification
    await DailyNotification.scheduleUserNotification({
      schedule: '0 9 * * *',
      title: 'Daily Update',
      body: 'Content ready'
    });

    // Verify status
    const status = await DailyNotification.getDualScheduleStatus();
    expect(status.nextRuns.length).toBe(2);
  });
});
```

## Troubleshooting

### Common Issues

#### Android

- **Permission Denied**: Ensure all required permissions are declared
- **WorkManager Not Running**: Check battery optimization settings
- **Database Errors**: Verify Room database schema migration

#### iOS

- **Background Tasks Not Running**: Check Background App Refresh settings
- **Core Data Errors**: Verify Core Data model compatibility
- **Notification Permissions**: Request notification permissions

#### Web

- **Service Worker Not Registering**: Ensure HTTPS and proper file paths
- **Push Notifications Not Working**: Verify VAPID keys and server setup
- **IndexedDB Errors**: Check browser compatibility and storage quotas

### Debug Commands

```typescript
// Get comprehensive status
const status = await DailyNotification.getDualScheduleStatus();
console.log('Status:', status);

// Check registered callbacks
const callbacks = await DailyNotification.getRegisteredCallbacks();
console.log('Callbacks:', callbacks);

// Test callback firing
await DailyNotification.registerCallback('debug', {
  kind: 'local',
  target: 'debugCallback'
});

function debugCallback(event: CallbackEvent) {
  console.log('Debug callback fired:', event);
}
```

## Performance Considerations

### Memory Usage

- **Android**: Room database with connection pooling
- **iOS**: Core Data with lightweight contexts
- **Web**: IndexedDB with efficient indexing

### Battery Optimization

- **Android**: WorkManager with battery-aware constraints
- **iOS**: BGTaskScheduler with system-managed execution
- **Web**: Service Worker with efficient background sync

### Network Usage

- **Circuit Breaker**: Prevents excessive retry attempts
- **TTL-at-Fire**: Reduces unnecessary network calls
- **Exponential Backoff**: Intelligent retry scheduling

## Security Considerations

### Permissions

- **Minimal Permissions**: Only request necessary permissions
- **Runtime Checks**: Verify permissions before operations
- **Graceful Degradation**: Handle permission denials gracefully

### Data Protection

- **Local Storage**: Encrypted local storage on all platforms
- **Network Security**: HTTPS-only for all network operations
- **Callback Security**: Validate callback URLs and headers

### Privacy

- **No Personal Data**: Plugin doesn't collect personal information
- **Local Processing**: All processing happens locally
- **User Control**: Users can disable notifications and callbacks

## Support

### Documentation

- **API Reference**: Complete TypeScript definitions
- **Examples**: Comprehensive usage examples
- **Troubleshooting**: Common issues and solutions

### Community

- **GitHub Issues**: Report bugs and request features
- **Discussions**: Ask questions and share solutions
- **Contributing**: Submit pull requests and improvements

### Enterprise Support

- **Custom Implementations**: Tailored solutions for enterprise needs
- **Integration Support**: Help with complex integrations
- **Performance Optimization**: Custom performance tuning

---

**Next Steps**: After migration, explore the [Enterprise Callback Examples](./enterprise-callback-examples.md) for advanced integration patterns.
