UNPKG

notification-kit

Version:

A unified notification library for React + Capacitor apps. One API for push notifications, in-app notifications, and local notifications across Web, iOS, and Android.

617 lines (616 loc) 18 kB
import { L as Logger, D as DynamicLoader } from "./inApp-DOHkBonY.mjs"; import { C as ConfigValidator } from "./config-validator-CAcf6-xn.mjs"; class OneSignalNativeBridge { static isInitialized = false; /** * Initialize OneSignal on native platforms with runtime configuration */ static async initializeNative(config) { if (this.isInitialized) { Logger.warn("OneSignal native bridge already initialized"); return; } const isNative = await DynamicLoader.isNativePlatform(); if (!isNative) { return; } const platform = await DynamicLoader.getPlatform(); try { const capacitor = await DynamicLoader.loadCapacitorCore(); if (!capacitor) { throw new Error("Capacitor not available for native OneSignal initialization"); } await this.configureNativePlatform(platform, config); this.isInitialized = true; Logger.info(`OneSignal native bridge initialized for ${platform}`); } catch (error) { Logger.error("Failed to initialize OneSignal native bridge:", error); throw error; } } /** * Configure OneSignal for specific native platform */ static async configureNativePlatform(platform, config) { if (platform === "ios") { await this.configureIOS(config); } else if (platform === "android") { await this.configureAndroid(config); } } /** * Configure OneSignal for iOS */ static async configureIOS(config) { Logger.debug("iOS OneSignal configuration:", { appId: config.appId ? "***" : "not provided" // Log config status without exposing sensitive data }); } /** * Configure OneSignal for Android */ static async configureAndroid(config) { Logger.debug("Android OneSignal configuration:", { appId: config.appId ? "***" : "not provided" // Log config status without exposing sensitive data }); } /** * Get initialization status */ static isNativeInitialized() { return this.isInitialized; } /** * Reset initialization (useful for testing) */ static reset() { this.isInitialized = false; } } class OneSignalProvider { name = "onesignal"; type = "onesignal"; config = null; initialized = false; OneSignal = null; messageListeners = []; tokenListeners = []; errorListeners = []; /** * Initialize OneSignal provider */ async init(config) { try { ConfigValidator.validateOneSignalConfig(config); ConfigValidator.validateEnvironmentVariables("onesignal"); this.config = config; const isNative = await DynamicLoader.isNativePlatform(); if (isNative) { await OneSignalNativeBridge.initializeNative(config); this.initialized = true; await this.setupNativeEventListeners(); } else { const initOptions = { appId: config.appId, safari_web_id: config.safariWebId, autoPrompt: config.autoPrompt ?? true, autoResubscribe: config.autoResubscribe ?? true, path: config.path, serviceWorkerPath: config.serviceWorkerPath, serviceWorkerUpdaterPath: config.serviceWorkerUpdaterPath, notificationClickHandlerMatch: config.notificationClickHandlerMatch ?? "origin", notificationClickHandlerAction: config.notificationClickHandlerAction ?? "focusOrNavigate", allowLocalhostAsSecureOrigin: config.allowLocalhostAsSecureOrigin ?? false }; if (config.promptOptions) { initOptions.promptOptions = config.promptOptions; } if (config.welcomeNotification) { initOptions.welcomeNotification = config.welcomeNotification; } const oneSignalModule = await DynamicLoader.loadOneSignal(); if (!oneSignalModule) { throw new Error("OneSignal is required but not installed"); } this.OneSignal = oneSignalModule.default; await this.OneSignal.init(initOptions); this.initialized = true; await this.setupEventListeners(); } } catch (error) { this.handleError(new Error(`OneSignal initialization failed: ${error}`)); throw error; } } /** * Destroy OneSignal provider */ async destroy() { try { if (this.initialized) { this.initialized = false; this.config = null; this.messageListeners = []; this.tokenListeners = []; this.errorListeners = []; } } catch (error) { this.handleError(new Error(`OneSignal destroy failed: ${error}`)); throw error; } } /** * Request notification permission */ async requestPermission() { try { const isNative = await DynamicLoader.isNativePlatform(); if (isNative) { return await this.requestNativePermission(); } else { return await this.requestWebPermission(); } } catch (error) { this.handleError(new Error(`Permission request failed: ${error}`)); return false; } } /** * Check notification permission status */ async checkPermission() { try { const isNative = await DynamicLoader.isNativePlatform(); if (isNative) { return await this.checkNativePermission(); } else { return await this.checkWebPermission(); } } catch (error) { this.handleError(new Error(`Permission check failed: ${error}`)); return "denied"; } } /** * Get OneSignal player ID (token) */ async getToken() { try { if (!this.OneSignal) { throw new Error("OneSignal not initialized"); } const playerId = await this.OneSignal.getUserId(); if (playerId) { return playerId; } else { throw new Error("No OneSignal player ID available"); } } catch (error) { this.handleError(new Error(`Token retrieval failed: ${error}`)); throw error; } } /** * Refresh OneSignal token */ async refreshToken() { try { const newToken = await this.getToken(); this.notifyTokenListeners(newToken); return newToken; } catch (error) { this.handleError(new Error(`Token refresh failed: ${error}`)); throw error; } } /** * Delete OneSignal token */ async deleteToken() { try { if (!this.OneSignal) { throw new Error("OneSignal not initialized"); } await this.OneSignal.logoutUser(); } catch (error) { this.handleError(new Error(`Token deletion failed: ${error}`)); throw error; } } /** * Subscribe to tag (OneSignal's equivalent of topics) */ async subscribe(topic) { try { if (!this.OneSignal) { throw new Error("OneSignal not initialized"); } await this.OneSignal.sendTag(topic, "true"); } catch (error) { this.handleError(new Error(`Tag subscription failed: ${error}`)); throw error; } } /** * Unsubscribe from tag */ async unsubscribe(topic) { try { if (!this.OneSignal) { throw new Error("OneSignal not initialized"); } await this.OneSignal.deleteTag(topic); } catch (error) { this.handleError(new Error(`Tag unsubscription failed: ${error}`)); throw error; } } /** * Get subscribed tags */ async getSubscriptions() { try { if (!this.OneSignal) { throw new Error("OneSignal not initialized"); } const tags = await this.OneSignal.getTags(); return Object.keys(tags || {}); } catch (error) { this.handleError(new Error(`Get subscriptions failed: ${error}`)); throw error; } } /** * Send notification (requires REST API) */ async sendNotification(payload) { if (!this.config?.restApiKey) { throw new Error("REST API key required for sending notifications"); } try { const response = await fetch( "https://onesignal.com/api/v1/notifications", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Basic ${this.config.restApiKey}` }, body: JSON.stringify({ app_id: this.config.appId, headings: { en: payload.notification?.title || "Notification" }, contents: { en: payload.notification?.body || "" }, data: payload.data, included_segments: ["All"] }) } ); if (!response.ok) { throw new Error(`OneSignal API error: ${response.statusText}`); } } catch (error) { this.handleError(new Error(`Send notification failed: ${error}`)); throw error; } } /** * Listen for messages */ onMessage(callback) { this.messageListeners.push(callback); return () => { const index = this.messageListeners.indexOf(callback); if (index > -1) { this.messageListeners.splice(index, 1); } }; } /** * Listen for token refresh */ onTokenRefresh(callback) { this.tokenListeners.push(callback); return () => { const index = this.tokenListeners.indexOf(callback); if (index > -1) { this.tokenListeners.splice(index, 1); } }; } /** * Listen for errors */ onError(callback) { this.errorListeners.push(callback); return () => { const index = this.errorListeners.indexOf(callback); if (index > -1) { this.errorListeners.splice(index, 1); } }; } /** * Check if OneSignal is supported */ async isSupported() { try { const isNative = await DynamicLoader.isNativePlatform(); if (isNative) { return true; } else { return typeof window !== "undefined" && "serviceWorker" in navigator && "PushManager" in window; } } catch (_error) { return false; } } /** * Get provider capabilities */ async getCapabilities() { const isWeb = !await DynamicLoader.isNativePlatform(); return { pushNotifications: true, topics: true, // Using tags richMedia: true, actions: true, backgroundSync: true, analytics: true, segmentation: true, scheduling: true, geofencing: false, inAppMessages: true, webPush: isWeb, badges: !isWeb, sounds: true, vibration: !isWeb, lights: !isWeb, bigText: !isWeb, bigPicture: !isWeb, inbox: false, progress: false, channels: !isWeb, groups: !isWeb, categories: true, quietHours: true, deliveryReceipts: true, clickTracking: true, impressionTracking: true, customData: true, multipleDevices: true, userTags: true, triggers: true, templates: true, abTesting: true, automation: true, journeys: true, realTimeUpdates: true }; } /** * Setup native event listeners for Capacitor */ async setupNativeEventListeners() { try { const pushNotificationsModule = await DynamicLoader.loadPushNotifications(); if (!pushNotificationsModule) { throw new Error("Push notifications module not available"); } const { PushNotifications } = pushNotificationsModule; await PushNotifications.addListener("pushNotificationReceived", (notification) => { const payload = { data: notification.data || {}, notification: { title: notification.title || "", body: notification.body || "", ...notification.id && { id: notification.id }, ...notification.badge && { badge: notification.badge.toString() } } }; this.notifyMessageListeners(payload); }); await PushNotifications.addListener("pushNotificationActionPerformed", (notificationAction) => { const payload = { data: notificationAction.notification.data || {}, notification: { title: notificationAction.notification.title || "", body: notificationAction.notification.body || "", ...notificationAction.notification.id && { id: notificationAction.notification.id } } }; this.notifyMessageListeners(payload); }); await PushNotifications.addListener("registration", (token) => { this.notifyTokenListeners(token.value); }); await PushNotifications.addListener("registrationError", (error) => { this.handleError(new Error(`Registration error: ${error.error}`)); }); } catch (error) { this.handleError(new Error(`Native event listener setup failed: ${error}`)); } } /** * Setup event listeners */ async setupEventListeners() { try { if (!this.OneSignal) { throw new Error("OneSignal not initialized"); } const oneSignalInstance = this.OneSignal; oneSignalInstance.on("notificationReceived", (notification) => { const notificationData = notification; const notificationObj = { title: notificationData.heading, body: notificationData.content }; if (notificationData.icon) notificationObj.icon = notificationData.icon; if (notificationData.badge) notificationObj.badge = notificationData.badge; if (notificationData.image) notificationObj.image = notificationData.image; const payload = { data: notificationData.additionalData || {}, notification: notificationObj }; this.notifyMessageListeners(payload); }); oneSignalInstance.on("notificationClicked", (notification) => { const notificationData = notification; const notificationObj = { title: notificationData.heading, body: notificationData.content }; if (notificationData.icon) notificationObj.icon = notificationData.icon; if (notificationData.badge) notificationObj.badge = notificationData.badge; if (notificationData.image) notificationObj.image = notificationData.image; const payload = { data: notificationData.additionalData || {}, notification: notificationObj }; this.notifyMessageListeners(payload); }); oneSignalInstance.on("subscriptionChanged", (isSubscribed) => { if (isSubscribed) { this.getToken().then((token) => { this.notifyTokenListeners(token); }).catch((error) => { this.handleError( new Error( `Token refresh on subscription change failed: ${error}` ) ); }); } }); } catch (error) { this.handleError(new Error(`Event listener setup failed: ${error}`)); } } /** * Request native permission */ async requestNativePermission() { try { const pushNotificationsModule = await DynamicLoader.loadPushNotifications(); if (!pushNotificationsModule) { throw new Error("Push notifications require @capacitor/push-notifications"); } const { PushNotifications } = pushNotificationsModule; const result = await PushNotifications.requestPermissions(); return result.receive === "granted"; } catch (_error) { return false; } } /** * Check native permission */ async checkNativePermission() { try { const pushNotificationsModule = await DynamicLoader.loadPushNotifications(); if (!pushNotificationsModule) { throw new Error("Push notifications require @capacitor/push-notifications"); } const { PushNotifications } = pushNotificationsModule; const result = await PushNotifications.checkPermissions(); if (result.receive === "granted") { return "granted"; } else if (result.receive === "denied") { return "denied"; } else if (result.receive === "prompt") { return "prompt"; } else { return "unknown"; } } catch (_error) { return "denied"; } } /** * Request web permission */ async requestWebPermission() { try { if (!this.OneSignal) { throw new Error("OneSignal not initialized"); } const permission = await this.OneSignal.showSlidedownPrompt(); return permission; } catch (_error) { if ("Notification" in window) { const permission = await Notification.requestPermission(); return permission === "granted"; } return false; } } /** * Check web permission */ async checkWebPermission() { try { if (!this.OneSignal) { throw new Error("OneSignal not initialized"); } const isSubscribed = await this.OneSignal.isPushNotificationsEnabled(); return isSubscribed ? "granted" : "prompt"; } catch (_error) { if ("Notification" in window) { const permission = Notification.permission; if (permission === "default") { return "prompt"; } return permission; } return "denied"; } } /** * Notify message listeners */ notifyMessageListeners(payload) { this.messageListeners.forEach((listener) => { try { listener(payload); } catch (error) { this.handleError(new Error(`Message listener error: ${error}`)); } }); } /** * Notify token listeners */ notifyTokenListeners(token) { this.tokenListeners.forEach((listener) => { try { listener(token); } catch (error) { this.handleError(new Error(`Token listener error: ${error}`)); } }); } /** * Handle errors */ handleError(error) { this.errorListeners.forEach((listener) => { try { listener(error); } catch (listenerError) { } }); } } export { OneSignalProvider }; //# sourceMappingURL=OneSignalProvider-mRblKTku.mjs.map