import { EventBus } from './core/modules/EventBus' ; import { Data } from './modules/Data/Data' ; import { Api } from './modules/Api/Api' ; import { PushServiceDefault } from './services/PushService/drivers/PushServiceDefault/PushServiceDefault' ; import { sendFatalLogToRemoteServer } from './helpers/logger' ; import { message as messagesLog } from './storage' ; import { PERIOD_GOAL_EVENT , EVENT_ON_PUSH_DELIVERY , EVENT_ON_NOTIFICATION_CLICK , EVENT_ON_NOTIFICATION_CLOSE , EVENT_ON_PUT_NEW_MESSAGE_TO_INBOX_STORE } from './constants' ; import { parseSerializedNotificationParams } from './functions' ; import { Logger } from './logger' ; import WorkerPushwooshGlobal from './worker/global' ; import PushwooshNotification from './worker/notification' ; import NotificationPayload from './models/NotificationPayload' ; import InboxMessages from './models/InboxMessages' ; import InboxMessagesPublic from './modules/InboxMessagesPublic' ; const eventBus = new EventBus ( ) ; const data = new Data ( ) ; const api = new Api ( eventBus , data ) ; const Pushwoosh = self . Pushwoosh = new WorkerPushwooshGlobal ( eventBus , data , api ) ; const clickedNotifications = [ ] ; self . addEventListener ( 'install' , onInstallEventHandler ) ; self . addEventListener ( 'activate' , onActivateEventHandler ) ; self . addEventListener ( 'push' , onPushEventHandler ) ; self . addEventListener ( 'notificationclick' , onClickNotificationEventHandler ) ; self . addEventListener ( 'notificationclose' , onCloseNotificationEventHandler ) ; self . addEventListener ( 'pushsubscriptionchange' , onPushSubscriptionChange ) ; param event function onInstallEventHandler ( event ) { async function onInstall ( ) { await Promise . all ( [ Pushwoosh . data . setServiceWorkerVersion ( __VERSION__ ) , Logger . write ( 'info' , 'install' ) ] ) ; await self . skipWaiting ( ) ; } return event . waitUntil ( onInstall ( ) . catch ( onInstallFailure ) ) ; } param event function onActivateEventHandler ( event ) { async function onActivate ( ) { await Promise . all ( [ Logger . write ( 'info' , 'activate' ) ] ) ; await self . clients . claim ( ) ; } event . waitUntil ( onActivate ( ) . catch ( onActivateFailure ) ) ; } param event function onPushEventHandler ( event ) { async function onPush ( event ) { await self . clients . claim ( ) ; const payload = await event . data . json ( ) ; const notificationPayload = new NotificationPayload ( payload ) ; const notificationOptions = await notificationPayload . getNotificationOptionsPayload ( ) ; const notificationShowOptions = await notificationPayload . getShowNotificationOptions ( ) ; const messageHash = notificationPayload . messageHash ; await Logger . write ( 'info' , JSON . stringify ( notificationOptions ) , 'onPush' ) ; const notification = new PushwooshNotification ( notificationShowOptions , notificationPayload . duration , notificationPayload . body , await notificationPayload . getTitle ( ) ) ; const callbacks = Pushwoosh . getListeners ( 'onPush' ) ; await callbacks . reduce ( ( pr , fun ) => pr . then ( ( ) => fun ( notification ) ) , Promise . resolve ( ) ) ; const onPushActions = [ notification . show ( ) , messagesLog . add ( { payload : payload , parsedPayload : notificationOptions , showOptions : notificationShowOptions } ) , broadcastClients ( { type : EVENT_ON_PUSH_DELIVERY , payload : notificationOptions } ) , ] ; if ( messageHash ) { onPushActions . push ( Pushwoosh . initApi ( ) . then ( ( ) => Pushwoosh . api . messageDeliveryEvent ( messageHash , true , notificationOptions . metaData ) ) ) ; } if ( notificationPayload . inboxId !== '' ) { const inboxMessages = new InboxMessages ( Pushwoosh . eventBus , Pushwoosh . data , Pushwoosh . api ) ; const inboxMessagesPublic = new InboxMessagesPublic ( Pushwoosh . data , Pushwoosh . api , inboxMessages ) ; const inboxMessagePayload = await notificationPayload . getInboxMessage ( ) ; const payload = await inboxMessagesPublic . publicMessageBuilder ( inboxMessagePayload ) ; onPushActions . push ( inboxMessages . putMessage ( inboxMessagePayload ) , broadcastClients ( { type : EVENT_ON_PUT_NEW_MESSAGE_TO_INBOX_STORE , payload } ) ) ; } await Promise . all ( onPushActions ) ; } event . waitUntil ( onPush ( event ) . catch ( ( error ) => onPushFailure ( error , event ) ) ) ; } param event function onClickNotificationEventHandler ( event ) { async function onClickNotification ( event ) { await self . clients . claim ( ) ; const notificationOptions = await parseNotificationEvent ( event ) ; const { messageHash , metaData , url , code , inboxId } = notificationOptions ; if ( code ) { clickedNotifications . push ( code ) ; } if ( inboxId !== '' ) { const inboxMessages = new InboxMessages ( Pushwoosh . eventBus , Pushwoosh . data , Pushwoosh . api ) ; const message = await inboxMessages . getMessage ( inboxId ) ; ( < TInboxMessageStatusOpen > message . status ) = 3 ; await inboxMessages . putMessage ( message ) ; } event . notification . close ( ) ; const message = { type : EVENT_ON_NOTIFICATION_CLICK , payload : notificationOptions } ; if ( url ) { event . waitUntil ( self . clients . matchAll ( { type : 'window' } ) . then ( ( windowClients ) => { return focusWindow ( windowClients , url ) ; } ) . then ( ( isFocusOnNewWindowClient ) => { if ( isFocusOnNewWindowClient ) { Pushwoosh . data . setDelayedEvent ( message ) ; } } ) ) ; } return Promise . all ( [ Pushwoosh . initApi ( ) . then ( ( ) => Pushwoosh . api . pushStat ( messageHash , true , metaData ) ) , Pushwoosh . data . setLastOpenMessage ( { url , messageHash , expiry : Date . now ( ) + PERIOD_GOAL_EVENT } ) , broadcastClients ( message ) ] ) ; } event . waitUntil ( onClickNotification ( event ) . catch ( onClickNotificationFailure ) ) ; } param event function onCloseNotificationEventHandler ( event ) { async function closeNotification ( event ) { await self . clients . claim ( ) ; const notificationOptions = await parseNotificationEvent ( event ) ; const { code } = notificationOptions ; event . notification . close ( ) ; if ( ! code ) { return ; } const index = clickedNotifications . indexOf ( code ) ; if ( index >= 0 ) { clickedNotifications . splice ( index , 1 ) ; } else { return broadcastClients ( { type : EVENT_ON_NOTIFICATION_CLOSE , payload : notificationOptions } ) ; } } event . waitUntil ( closeNotification ( event ) . catch ( closeNotificationFailure ) ) ; } async function onPushSubscriptionChange ( event ) { async function changePushSubscription ( event ) { let subscription = event . newSubscription ; if ( ! subscription ) { subscription = await self . registration . pushManager . getSubscription ( ) ; if ( ! subscription ) { return ; } } const pushService = new PushServiceDefault ( api , data , { } ) ; await pushService . subscribe ( subscription ) ; } event . waitUntil ( changePushSubscription ( event ) . catch ( pushSubscriptionChangeFailure ) ) ; } param msg async function broadcastClients ( msg ) { const clients = await self . clients . matchAll ( ) ; clients . forEach ( client => client . postMessage ( msg ) ) ; } async function focusWindow ( windowClients , url ) { const { hostname : openedHostname , pathname : openedPathname , } = new URL ( url , self . location . origin ) ; const clientWithSameAddress = windowClients . find ( ( windowClient ) => { const { hostname : windowClientHostname , pathname : windowClientPathname } = new URL ( windowClient . url ) ; return windowClientHostname === openedHostname && windowClientPathname === openedPathname ; } ) ; if ( clientWithSameAddress ) { await clientWithSameAddress . focus ( ) ; return false ; } await self . clients . openWindow ( url ) . then ( ( newClientWindow ) => { if ( ! newClientWindow ) { return ; } newClientWindow . focus ( ) ; } ) ; return true ; } async function parseNotificationEvent ( event ) { const { notification = { } } = event ; const { data : notificationData } = notification ; const notificationTag = parseSerializedNotificationParams ( notification . tag , { } ) ; let url = '' ; if ( event . action && Array . isArray ( notificationData . buttons ) ) { const button = notificationData . buttons . find ( ( button ) => button . action === event . action ) || { } ; url = button . url ; } else { url = notificationTag . url ; } return { requireInteraction : notification . requireInteraction , title : notification . title , body : notification . body , icon : notification . icon , buttons : notificationData . buttons , duration : notificationData . duration , image : notificationData . image , code : notificationData . code , campaignCode : notificationData . campaignCode , inboxId : notificationData . inboxId , messageHash : notificationTag . messageHash , customData : notificationTag . customData , metaData : notificationTag . metaData , openUrl : notificationTag . url , tag : notification . tag , url } ; } async function onInstallFailure ( error ) { const applicationCode = await Pushwoosh . data . getApplicationCode ( ) ; const workerVersion = await Pushwoosh . data . getServiceWorkerVersion ( ) ; await sendFatalLogToRemoteServer ( { message : 'Error in onInstallEventHandler' , code : 'FATAL-SW-001' , error , applicationCode , workerVersion } ) ; } async function onActivateFailure ( error ) { const applicationCode = await Pushwoosh . data . getApplicationCode ( ) ; const workerVersion = await Pushwoosh . data . getServiceWorkerVersion ( ) ; await sendFatalLogToRemoteServer ( { message : 'Error in onActivateEventHandler' , code : 'FATAL-SW-002' , error , applicationCode , workerVersion } ) ; } async function onPushFailure ( error , event ) { const applicationCode = await Pushwoosh . data . getApplicationCode ( ) ; const workerVersion = await Pushwoosh . data . getServiceWorkerVersion ( ) ; await sendFatalLogToRemoteServer ( { message : 'Error in onPushEventHandler' , code : 'FATAL-SW-003' , error , applicationCode , workerVersion } ) ; if ( ! ( error instanceof Error ) ) { error = new Error ( error ) ; } return messagesLog . add ( { error : `${ error }` , stack : error . stack , payload : event . data && event . data . text ( ) } ) ; } async function onClickNotificationFailure ( error ) { const applicationCode = await Pushwoosh . data . getApplicationCode ( ) ; const workerVersion = await Pushwoosh . data . getServiceWorkerVersion ( ) ; await sendFatalLogToRemoteServer ( { message : 'Error in onNotificationClickEventHandler' , code : 'FATAL-SW-004' , error , applicationCode , workerVersion } ) ; } async function closeNotificationFailure ( error ) { const applicationCode = await Pushwoosh . data . getApplicationCode ( ) ; const workerVersion = await Pushwoosh . data . getServiceWorkerVersion ( ) ; await sendFatalLogToRemoteServer ( { message : 'Error in onNotificationCloseEventHandler' , code : 'FATAL-SW-005' , error , applicationCode , workerVersion } ) ; } async function pushSubscriptionChangeFailure ( error ) { const applicationCode = await Pushwoosh . data . getApplicationCode ( ) ; const workerVersion = await Pushwoosh . data . getServiceWorkerVersion ( ) ; await sendFatalLogToRemoteServer ( { message : 'Error in onPushSubscriptionChange' , code : 'FATAL-SW-006' , error , applicationCode , workerVersion } ) ; }