You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

12 KiB

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, USE_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

npm install @timesafari/daily-notification-plugin@^2.0.0

Step 2: Update Import Statements

// 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)

// 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 * * *'
});
// 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

// 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

// 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

<!-- 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.USE_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="com.timesafari.dailynotification.NotifyReceiver"
          android:enabled="true"
          android:exported="false" />
<receiver android:name="com.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

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

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

<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
    <string>com.timesafari.dailynotification.content-fetch</string>
    <string>com.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

// 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

// 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

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

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

// 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 for advanced integration patterns.