Teardown

Notification Adapters

Push notification adapters for token registration and management.

Work in Progress: The notification adapter APIs are under active development and may change in future releases.

Notification adapters handle push notification token registration, permission requests, and notification event handling with your push notification provider.

Available Adapters

AdapterPackageBest For
ExpoNotificationsAdapterexpo-notificationsExpo projects
FirebaseMessagingAdapter@react-native-firebase/messagingFirebase Cloud Messaging
WixNotificationsAdapterreact-native-notificationsWix notifications library

Usage

Notification adapters are passed to TeardownCore to enable push notification support:

import { TeardownCore } from '@teardown/force-updates';
import { ExpoNotificationsAdapter } from '@teardown/force-updates/expo';
import { ExpoDeviceAdapter } from '@teardown/force-updates/adapters/expo';
import { MMKVStorageAdapter } from '@teardown/force-updates/adapters/mmkv';

const teardown = new TeardownCore({
  org_id: 'your-org-id',
  project_id: 'your-project-id',
  api_key: 'your-api-key',
  storageAdapter: new MMKVStorageAdapter(),
  deviceAdapter: new ExpoDeviceAdapter(),
  notificationAdapter: new ExpoNotificationsAdapter(), // Optional
});

// Access notifications via core
if (teardown.notifications) {
  const token = await teardown.notifications.getToken();
}

Adapter Interface

All notification adapters extend the abstract NotificationAdapter class:

abstract class NotificationAdapter {
  /** The notification platform this adapter supports (APNS, FCM, EXPO) */
  abstract get platform(): NotificationPlatformEnum;

  /** Get the current push notification token */
  abstract getToken(): Promise<string | null>;

  /** Request push notification permissions from the user */
  abstract requestPermissions(): Promise<PermissionStatus>;

  /** Subscribe to token refresh events */
  abstract onTokenRefresh(listener: (token: string) => void): Unsubscribe;

  /** Subscribe to foreground notification events */
  abstract onNotificationReceived(listener: (notification: PushNotification) => void): Unsubscribe;

  /** Subscribe to notification opened events (user taps) */
  abstract onNotificationOpened(listener: (notification: PushNotification) => void): Unsubscribe;

  /** Subscribe to data-only message events (silent/background push) */
  abstract onDataMessage(listener: (message: DataMessage) => void): Unsubscribe;
}

PermissionStatus

interface PermissionStatus {
  /** Whether notifications permission is granted */
  granted: boolean;
  /** Whether the user can be prompted again (iOS specific) */
  canAskAgain: boolean;
}

PushNotification

interface PushNotification {
  title?: string;
  body?: string;
  data?: Record<string, unknown>;
}

DataMessage

interface DataMessage {
  data: Record<string, unknown>;
}

NotificationPlatformEnum

enum NotificationPlatformEnum {
  APNS = "APNS",  // Apple Push Notification Service
  FCM = "FCM",    // Firebase Cloud Messaging
  EXPO = "EXPO",  // Expo Push Notifications
}

Choosing an Adapter

If you're using...Use this adapter
Expo with expo-notificationsExpoNotificationsAdapter
Firebase Cloud MessagingFirebaseMessagingAdapter
Wix react-native-notificationsWixNotificationsAdapter
Other push libraryImplement custom adapter

Custom Adapter

Extend the NotificationAdapter abstract class:

import {
  NotificationAdapter,
  NotificationPlatformEnum,
  type PermissionStatus,
  type PushNotification,
  type DataMessage,
  type Unsubscribe,
} from '@teardown/force-updates';

class CustomNotificationsAdapter extends NotificationAdapter {
  get platform(): NotificationPlatformEnum {
    return NotificationPlatformEnum.FCM;
  }

  async getToken(): Promise<string | null> {
    return await myNotificationLib.getToken();
  }

  async requestPermissions(): Promise<PermissionStatus> {
    const granted = await myNotificationLib.requestPermission();
    return { granted, canAskAgain: !granted };
  }

  onTokenRefresh(listener: (token: string) => void): Unsubscribe {
    const subscription = myNotificationLib.onTokenRefresh(listener);
    return () => subscription.remove();
  }

  onNotificationReceived(listener: (notification: PushNotification) => void): Unsubscribe {
    const subscription = myNotificationLib.onMessage((msg) => {
      listener({
        title: msg.notification?.title,
        body: msg.notification?.body,
        data: msg.data,
      });
    });
    return () => subscription();
  }

  onNotificationOpened(listener: (notification: PushNotification) => void): Unsubscribe {
    const subscription = myNotificationLib.onNotificationOpened((msg) => {
      listener({
        title: msg.notification?.title,
        body: msg.notification?.body,
        data: msg.data,
      });
    });
    return () => subscription();
  }

  onDataMessage(listener: (message: DataMessage) => void): Unsubscribe {
    const subscription = myNotificationLib.onDataMessage((msg) => {
      listener({ data: msg.data ?? {} });
    });
    return () => subscription();
  }
}