@rivium/push-web 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,547 @@
1
+ /**
2
+ * RiviumPush Web SDK
3
+ * Push notifications for browsers - Firebase alternative
4
+ *
5
+ * Features:
6
+ * - Web Push API for background notifications
7
+ * - MQTT over WebSocket for real-time foreground messages
8
+ * - Service Worker integration
9
+ * - Rich notifications with images, action buttons, and localization
10
+ * - Analytics event tracking
11
+ * - Detailed error codes and handling
12
+ * - Network and app state monitoring
13
+ * - Works without Firebase
14
+ *
15
+ * @packageDocumentation
16
+ */
17
+ /**
18
+ * Standardized error codes for RiviumPush SDK.
19
+ * These codes help developers identify and handle specific error scenarios.
20
+ */
21
+ export declare enum RiviumPushErrorCode {
22
+ CONNECTION_FAILED = 1000,
23
+ CONNECTION_TIMEOUT = 1001,
24
+ CONNECTION_LOST = 1002,
25
+ CONNECTION_REFUSED = 1003,
26
+ AUTHENTICATION_FAILED = 1004,
27
+ SSL_ERROR = 1005,
28
+ BROKER_UNAVAILABLE = 1006,
29
+ SUBSCRIPTION_FAILED = 1100,
30
+ UNSUBSCRIPTION_FAILED = 1101,
31
+ INVALID_TOPIC = 1102,
32
+ MESSAGE_DELIVERY_FAILED = 1200,
33
+ MESSAGE_PARSE_ERROR = 1201,
34
+ MESSAGE_TIMEOUT = 1202,
35
+ INVALID_CONFIG = 1300,
36
+ MISSING_API_KEY = 1301,
37
+ /** @deprecated No longer used - server URL is internal */
38
+ MISSING_SERVER_URL = 1302,
39
+ INVALID_CREDENTIALS = 1303,
40
+ REGISTRATION_FAILED = 1400,
41
+ DEVICE_ID_GENERATION_FAILED = 1401,
42
+ SERVER_ERROR = 1402,
43
+ NETWORK_ERROR = 1403,
44
+ NOT_INITIALIZED = 1500,
45
+ NOT_CONNECTED = 1501,
46
+ ALREADY_CONNECTED = 1502,
47
+ SERVICE_NOT_RUNNING = 1503,
48
+ PERMISSION_DENIED = 1600,
49
+ PERMISSION_DISMISSED = 1601,
50
+ UNKNOWN_ERROR = 9999
51
+ }
52
+ /**
53
+ * Represents a RiviumPush error with code and additional details
54
+ */
55
+ export declare class RiviumPushError extends Error {
56
+ /** The error code */
57
+ readonly code: RiviumPushErrorCode;
58
+ /** Additional details about the error */
59
+ readonly details?: string;
60
+ constructor(code: RiviumPushErrorCode, details?: string);
61
+ toJSON(): {
62
+ code: RiviumPushErrorCode;
63
+ message: string;
64
+ details: string | undefined;
65
+ };
66
+ }
67
+ /**
68
+ * Analytics event types for tracking SDK usage.
69
+ * Use with setAnalyticsHandler to track SDK events.
70
+ */
71
+ export declare enum RiviumPushAnalyticsEvent {
72
+ /** SDK was initialized */
73
+ SDK_INITIALIZED = "sdkInitialized",
74
+ /** Device was registered */
75
+ DEVICE_REGISTERED = "deviceRegistered",
76
+ /** Device was unregistered */
77
+ DEVICE_UNREGISTERED = "deviceUnregistered",
78
+ /** Push message was received */
79
+ MESSAGE_RECEIVED = "messageReceived",
80
+ /** Push message was displayed as notification */
81
+ MESSAGE_DISPLAYED = "messageDisplayed",
82
+ /** Notification was clicked */
83
+ NOTIFICATION_CLICKED = "notificationClicked",
84
+ /** Action button was clicked */
85
+ ACTION_CLICKED = "actionClicked",
86
+ /** MQTT connected successfully */
87
+ CONNECTED = "connected",
88
+ /** MQTT disconnected */
89
+ DISCONNECTED = "disconnected",
90
+ /** Connection error occurred */
91
+ CONNECTION_ERROR = "connectionError",
92
+ /** Retry attempt started (during exponential backoff) */
93
+ RETRY_STARTED = "retryStarted",
94
+ /** Topic subscribed */
95
+ TOPIC_SUBSCRIBED = "topicSubscribed",
96
+ /** Topic unsubscribed */
97
+ TOPIC_UNSUBSCRIBED = "topicUnsubscribed",
98
+ /** Network state changed */
99
+ NETWORK_STATE_CHANGED = "networkStateChanged",
100
+ /** App state changed (visible/hidden) */
101
+ APP_STATE_CHANGED = "appStateChanged",
102
+ /** Permission requested */
103
+ PERMISSION_REQUESTED = "permissionRequested",
104
+ /** Permission granted */
105
+ PERMISSION_GRANTED = "permissionGranted",
106
+ /** Permission denied */
107
+ PERMISSION_DENIED = "permissionDenied"
108
+ }
109
+ /**
110
+ * Log levels for the RiviumPush SDK.
111
+ * Controls verbosity of logging output.
112
+ */
113
+ export declare enum RiviumPushLogLevel {
114
+ /** No logging at all (for production) */
115
+ NONE = 0,
116
+ /** Only errors */
117
+ ERROR = 1,
118
+ /** Errors and warnings */
119
+ WARNING = 2,
120
+ /** Errors, warnings, and info messages */
121
+ INFO = 3,
122
+ /** All messages including debug output (default for development) */
123
+ DEBUG = 4,
124
+ /** Everything including very detailed traces */
125
+ VERBOSE = 5
126
+ }
127
+ /**
128
+ * Network type enumeration
129
+ */
130
+ export declare enum NetworkType {
131
+ WIFI = "wifi",
132
+ CELLULAR = "cellular",
133
+ ETHERNET = "ethernet",
134
+ NONE = "none",
135
+ UNKNOWN = "unknown"
136
+ }
137
+ /**
138
+ * Represents the current network state
139
+ */
140
+ export interface NetworkState {
141
+ /** Whether network is currently available */
142
+ isAvailable: boolean;
143
+ /** The type of network connection */
144
+ networkType: NetworkType;
145
+ /** Effective connection type (4g, 3g, 2g, slow-2g) */
146
+ effectiveType?: string;
147
+ /** Downlink speed in Mbps */
148
+ downlink?: number;
149
+ /** Round-trip time in ms */
150
+ rtt?: number;
151
+ }
152
+ /**
153
+ * Represents the app's visibility state
154
+ */
155
+ export interface AppState {
156
+ /** Whether the page is currently visible */
157
+ isVisible: boolean;
158
+ /** Visibility state: visible, hidden, prerender */
159
+ visibilityState: DocumentVisibilityState;
160
+ }
161
+ /**
162
+ * Represents the reconnection state during automatic retry
163
+ */
164
+ export interface ReconnectionState {
165
+ /** Current retry attempt number (0-based) */
166
+ retryAttempt: number;
167
+ /** Time in milliseconds until next retry */
168
+ nextRetryMs: number;
169
+ /** Maximum retry attempts */
170
+ maxRetryAttempts: number;
171
+ }
172
+ /**
173
+ * Configuration for initializing RiviumPush Web SDK
174
+ *
175
+ * `apiKey` is required.
176
+ * MQTT configuration is automatically fetched from the server during initialization.
177
+ */
178
+ export interface RiviumPushConfig {
179
+ /** Your RiviumPush API key (starts with rv_live_) - REQUIRED */
180
+ apiKey: string;
181
+ /** Path to RiviumPush service worker file */
182
+ serviceWorkerPath?: string;
183
+ /** VAPID public key for Web Push */
184
+ vapidPublicKey?: string;
185
+ /** Auto-register service worker (default: true) */
186
+ autoRegisterServiceWorker?: boolean;
187
+ /** MQTT QoS level (default: 1) */
188
+ mqttQos?: 0 | 1 | 2;
189
+ /** Maximum reconnect attempts (default: 10) */
190
+ maxReconnectAttempts?: number;
191
+ /** Initial log level (default: DEBUG in dev, ERROR in prod) */
192
+ logLevel?: RiviumPushLogLevel;
193
+ }
194
+ /**
195
+ * Notification action button
196
+ */
197
+ export interface NotificationAction {
198
+ /** Unique action identifier */
199
+ id: string;
200
+ /** Button display text */
201
+ title: string;
202
+ /** URL to open when action is clicked */
203
+ action?: string;
204
+ /** Icon for the action button */
205
+ icon?: string;
206
+ /** If true, action is marked as destructive */
207
+ destructive?: boolean;
208
+ /** If true, requires authentication */
209
+ authRequired?: boolean;
210
+ }
211
+ /**
212
+ * Localized content for i18n support
213
+ */
214
+ export interface LocalizedContent {
215
+ /** Locale code (e.g., 'en', 'fr', 'de') */
216
+ locale: string;
217
+ /** Localized title */
218
+ title: string;
219
+ /** Localized body */
220
+ body: string;
221
+ }
222
+ /**
223
+ * Push notification message with rich features
224
+ */
225
+ export interface RiviumPushMessage {
226
+ /** Notification title */
227
+ title: string;
228
+ /** Notification body */
229
+ body: string;
230
+ /** Custom data payload */
231
+ data?: Record<string, any>;
232
+ /** If true, message is delivered silently */
233
+ silent?: boolean;
234
+ /** Large image URL */
235
+ imageUrl?: string;
236
+ /** Icon/avatar URL */
237
+ iconUrl?: string;
238
+ /** Action buttons (max 2 in browsers) */
239
+ actions?: NotificationAction[];
240
+ /** Deep link URL */
241
+ deepLink?: string;
242
+ /** Badge count */
243
+ badge?: number;
244
+ /** Badge action: set, increment, decrement, clear */
245
+ badgeAction?: 'set' | 'increment' | 'decrement' | 'clear';
246
+ /** Custom sound name */
247
+ sound?: string;
248
+ /** Thread ID for grouping */
249
+ threadId?: string;
250
+ /** Collapse key for replacing notifications */
251
+ collapseKey?: string;
252
+ /** Category for filtering */
253
+ category?: string;
254
+ /** Priority: default, high, low */
255
+ priority?: 'default' | 'high' | 'low';
256
+ /** Time to live in seconds */
257
+ ttl?: number;
258
+ /** Localized content variations */
259
+ localizations?: LocalizedContent[];
260
+ /** Target timezone */
261
+ timezone?: string;
262
+ /** Unique message ID */
263
+ messageId?: string;
264
+ /** Campaign ID for analytics */
265
+ campaignId?: string;
266
+ /** @deprecated Use iconUrl instead */
267
+ icon?: string;
268
+ /** @deprecated Use imageUrl instead */
269
+ image?: string;
270
+ /** Notification tag for grouping (legacy) */
271
+ tag?: string;
272
+ }
273
+ /**
274
+ * Device registration options
275
+ */
276
+ export interface RegisterOptions {
277
+ /** User identifier */
278
+ userId?: string;
279
+ /** Additional metadata */
280
+ metadata?: Record<string, string>;
281
+ }
282
+ /**
283
+ * Connection state
284
+ */
285
+ export type ConnectionState = 'connecting' | 'connected' | 'disconnected' | 'error';
286
+ export type OnMessageCallback = (message: RiviumPushMessage) => void;
287
+ export type OnConnectionStateCallback = (state: ConnectionState) => void;
288
+ export type OnRegisteredCallback = (deviceId: string) => void;
289
+ export type OnErrorCallback = (error: Error) => void;
290
+ export type OnDetailedErrorCallback = (error: RiviumPushError) => void;
291
+ export type OnNotificationClickCallback = (message: RiviumPushMessage, action?: string) => void;
292
+ export type OnActionClickedCallback = (actionId: string, message: RiviumPushMessage) => void;
293
+ export type OnReconnectingCallback = (state: ReconnectionState) => void;
294
+ export type OnNetworkStateCallback = (state: NetworkState) => void;
295
+ export type OnAppStateCallback = (state: AppState) => void;
296
+ export type RiviumPushAnalyticsCallback = (event: RiviumPushAnalyticsEvent, properties?: Record<string, any>) => void;
297
+ /**
298
+ * RiviumPush Web SDK - Push notifications for browsers
299
+ *
300
+ * @example
301
+ * ```typescript
302
+ * import RiviumPush from '@rivium/push-web';
303
+ *
304
+ * // Initialize with API key
305
+ * // MQTT config is auto-fetched from server
306
+ * const riviumPush = new RiviumPush({
307
+ * apiKey: 'rv_live_your_api_key', // Get from Rivium Console
308
+ * });
309
+ *
310
+ * // Set up analytics tracking
311
+ * riviumPush.setAnalyticsHandler((event, properties) => {
312
+ * console.log('Analytics:', event, properties);
313
+ * });
314
+ *
315
+ * // Set up error handling
316
+ * riviumPush.onDetailedError((error) => {
317
+ * console.error('Error:', error.code, error.message, error.details);
318
+ * });
319
+ *
320
+ * // Set up message handling
321
+ * riviumPush.onMessage((message) => {
322
+ * console.log('Received:', message.title);
323
+ * });
324
+ *
325
+ * // Register device
326
+ * await riviumPush.register({ userId: 'user123' });
327
+ * ```
328
+ */
329
+ declare class RiviumPush {
330
+ private config;
331
+ private deviceId;
332
+ private pnSocket;
333
+ private serviceWorkerRegistration;
334
+ private pushSubscription;
335
+ private connectionState;
336
+ private reconnectAttempts;
337
+ private maxReconnectAttempts;
338
+ private reconnectTimer;
339
+ private subscribedTopics;
340
+ private badgeCount;
341
+ private initialized;
342
+ private initialMessage;
343
+ private mqttConfig;
344
+ private mqttConfigFetched;
345
+ private appId;
346
+ private appIdentifier;
347
+ private vapidPublicKey;
348
+ private logLevel;
349
+ private analyticsCallback;
350
+ private analyticsEnabled;
351
+ private onMessageCallback;
352
+ private onConnectionStateCallback;
353
+ private onRegisteredCallback;
354
+ private onErrorCallback;
355
+ private onDetailedErrorCallback;
356
+ private onNotificationClickCallback;
357
+ private onActionClickedCallback;
358
+ private onReconnectingCallback;
359
+ private onNetworkStateCallback;
360
+ private onAppStateCallback;
361
+ constructor(config: RiviumPushConfig);
362
+ /**
363
+ * Fetch MQTT and VAPID configuration from server
364
+ */
365
+ private fetchMqttConfig;
366
+ private log;
367
+ /**
368
+ * Set the log level for SDK logging.
369
+ *
370
+ * @example
371
+ * ```typescript
372
+ * // In production, reduce logging
373
+ * riviumPush.setLogLevel(RiviumPushLogLevel.ERROR);
374
+ * ```
375
+ */
376
+ setLogLevel(level: RiviumPushLogLevel): void;
377
+ /**
378
+ * Get current log level
379
+ */
380
+ getLogLevel(): RiviumPushLogLevel;
381
+ private trackEvent;
382
+ /**
383
+ * Enable analytics tracking with a custom handler.
384
+ *
385
+ * @example
386
+ * ```typescript
387
+ * riviumPush.setAnalyticsHandler((event, properties) => {
388
+ * // Send to your analytics service
389
+ * analytics.track(`rivium_push_${event}`, properties);
390
+ * });
391
+ * ```
392
+ */
393
+ setAnalyticsHandler(callback: RiviumPushAnalyticsCallback): void;
394
+ /**
395
+ * Disable analytics tracking
396
+ */
397
+ disableAnalytics(): void;
398
+ /**
399
+ * Check if analytics tracking is enabled
400
+ */
401
+ isAnalyticsEnabled(): boolean;
402
+ private emitError;
403
+ /**
404
+ * Register device for push notifications
405
+ */
406
+ register(options?: RegisterOptions): Promise<string>;
407
+ /**
408
+ * Wait for config to be fetched from server
409
+ */
410
+ private waitForConfig;
411
+ /**
412
+ * Unregister device and disconnect
413
+ */
414
+ unregister(): Promise<void>;
415
+ /**
416
+ * Subscribe to a topic
417
+ */
418
+ subscribeTopic(topic: string): Promise<void>;
419
+ /**
420
+ * Unsubscribe from a topic
421
+ */
422
+ unsubscribeTopic(topic: string): Promise<void>;
423
+ /**
424
+ * Check if connected to MQTT broker
425
+ */
426
+ isConnected(): boolean;
427
+ /**
428
+ * Get current device ID
429
+ */
430
+ getDeviceId(): string | null;
431
+ /**
432
+ * Set user ID
433
+ */
434
+ setUserId(userId: string): Promise<void>;
435
+ /**
436
+ * Clear user ID
437
+ */
438
+ clearUserId(): void;
439
+ /**
440
+ * Get the message that launched/opened the app (when user tapped a notification)
441
+ * Returns null if the app was not opened from a notification tap
442
+ */
443
+ getInitialMessage(): RiviumPushMessage | null;
444
+ /**
445
+ * Get current badge count
446
+ */
447
+ getBadgeCount(): number;
448
+ /**
449
+ * Set badge count
450
+ */
451
+ setBadgeCount(count: number): void;
452
+ /**
453
+ * Clear badge
454
+ */
455
+ clearBadge(): void;
456
+ /**
457
+ * Refresh MQTT JWT token (called automatically when token expires)
458
+ * Can also be called manually if needed
459
+ */
460
+ refreshMqttToken(): Promise<void>;
461
+ /**
462
+ * Get current network state
463
+ */
464
+ getNetworkState(): NetworkState;
465
+ /**
466
+ * Get current app (visibility) state
467
+ */
468
+ getAppState(): AppState;
469
+ /**
470
+ * Check if notifications are supported
471
+ */
472
+ static isSupported(): boolean;
473
+ /**
474
+ * Get current notification permission status
475
+ */
476
+ static getPermissionStatus(): NotificationPermission;
477
+ /**
478
+ * Set callback for receiving messages
479
+ */
480
+ onMessage(callback: OnMessageCallback): () => void;
481
+ /**
482
+ * Set callback for connection state changes
483
+ */
484
+ onConnectionState(callback: OnConnectionStateCallback): () => void;
485
+ /**
486
+ * Set callback for registration success
487
+ */
488
+ onRegistered(callback: OnRegisteredCallback): () => void;
489
+ /**
490
+ * Set callback for errors (simple)
491
+ */
492
+ onError(callback: OnErrorCallback): () => void;
493
+ /**
494
+ * Set callback for detailed errors with error codes
495
+ */
496
+ onDetailedError(callback: OnDetailedErrorCallback): () => void;
497
+ /**
498
+ * Set callback for notification clicks
499
+ */
500
+ onNotificationClick(callback: OnNotificationClickCallback): () => void;
501
+ /**
502
+ * Set callback for action button clicks
503
+ */
504
+ onActionClicked(callback: OnActionClickedCallback): () => void;
505
+ /**
506
+ * Set callback for reconnection state changes
507
+ */
508
+ onReconnecting(callback: OnReconnectingCallback): () => void;
509
+ /**
510
+ * Set callback for network state changes
511
+ */
512
+ onNetworkState(callback: OnNetworkStateCallback): () => void;
513
+ /**
514
+ * Set callback for app state changes (visibility)
515
+ */
516
+ onAppState(callback: OnAppStateCallback): () => void;
517
+ private detectNetworkType;
518
+ private handleNetworkChange;
519
+ private handleOnline;
520
+ private handleOffline;
521
+ private handleVisibilityChange;
522
+ private checkInitialMessage;
523
+ private registerServiceWorker;
524
+ private requestNotificationPermission;
525
+ private subscribeToPush;
526
+ private registerDevice;
527
+ private connectToGateway;
528
+ /**
529
+ * Handle incoming PNMessage from the protocol layer
530
+ */
531
+ private handlePNMessage;
532
+ private disconnectFromGateway;
533
+ private scheduleReconnect;
534
+ private handleMqttMessage;
535
+ private normalizeMessage;
536
+ private getLocalizedContent;
537
+ private handleBadge;
538
+ private handleServiceWorkerMessage;
539
+ private showRichNotification;
540
+ private updateFaviconBadge;
541
+ private setConnectionState;
542
+ private getOrCreateDeviceId;
543
+ private generateUUID;
544
+ private urlBase64ToUint8Array;
545
+ }
546
+ export default RiviumPush;
547
+ export { RiviumPush };
@@ -0,0 +1,2 @@
1
+ import{PNConfigBuilder as e,PNAuthFactory as t,PNSocket as i}from"@rivium/pn-protocol";var n;!function(e){e[e.CONNECTION_FAILED=1e3]="CONNECTION_FAILED",e[e.CONNECTION_TIMEOUT=1001]="CONNECTION_TIMEOUT",e[e.CONNECTION_LOST=1002]="CONNECTION_LOST",e[e.CONNECTION_REFUSED=1003]="CONNECTION_REFUSED",e[e.AUTHENTICATION_FAILED=1004]="AUTHENTICATION_FAILED",e[e.SSL_ERROR=1005]="SSL_ERROR",e[e.BROKER_UNAVAILABLE=1006]="BROKER_UNAVAILABLE",e[e.SUBSCRIPTION_FAILED=1100]="SUBSCRIPTION_FAILED",e[e.UNSUBSCRIPTION_FAILED=1101]="UNSUBSCRIPTION_FAILED",e[e.INVALID_TOPIC=1102]="INVALID_TOPIC",e[e.MESSAGE_DELIVERY_FAILED=1200]="MESSAGE_DELIVERY_FAILED",e[e.MESSAGE_PARSE_ERROR=1201]="MESSAGE_PARSE_ERROR",e[e.MESSAGE_TIMEOUT=1202]="MESSAGE_TIMEOUT",e[e.INVALID_CONFIG=1300]="INVALID_CONFIG",e[e.MISSING_API_KEY=1301]="MISSING_API_KEY",e[e.MISSING_SERVER_URL=1302]="MISSING_SERVER_URL",e[e.INVALID_CREDENTIALS=1303]="INVALID_CREDENTIALS",e[e.REGISTRATION_FAILED=1400]="REGISTRATION_FAILED",e[e.DEVICE_ID_GENERATION_FAILED=1401]="DEVICE_ID_GENERATION_FAILED",e[e.SERVER_ERROR=1402]="SERVER_ERROR",e[e.NETWORK_ERROR=1403]="NETWORK_ERROR",e[e.NOT_INITIALIZED=1500]="NOT_INITIALIZED",e[e.NOT_CONNECTED=1501]="NOT_CONNECTED",e[e.ALREADY_CONNECTED=1502]="ALREADY_CONNECTED",e[e.SERVICE_NOT_RUNNING=1503]="SERVICE_NOT_RUNNING",e[e.PERMISSION_DENIED=1600]="PERMISSION_DENIED",e[e.PERMISSION_DISMISSED=1601]="PERMISSION_DISMISSED",e[e.UNKNOWN_ERROR=9999]="UNKNOWN_ERROR"}(n||(n={}));const s={[n.CONNECTION_FAILED]:"Failed to connect to MQTT broker",[n.CONNECTION_TIMEOUT]:"Connection timed out",[n.CONNECTION_LOST]:"Connection to server was lost",[n.CONNECTION_REFUSED]:"Connection was refused by server",[n.AUTHENTICATION_FAILED]:"Authentication failed - invalid credentials",[n.SSL_ERROR]:"SSL/TLS handshake failed",[n.BROKER_UNAVAILABLE]:"MQTT broker is unavailable",[n.SUBSCRIPTION_FAILED]:"Failed to subscribe to topic",[n.UNSUBSCRIPTION_FAILED]:"Failed to unsubscribe from topic",[n.INVALID_TOPIC]:"Invalid topic format",[n.MESSAGE_DELIVERY_FAILED]:"Failed to deliver message",[n.MESSAGE_PARSE_ERROR]:"Failed to parse message payload",[n.MESSAGE_TIMEOUT]:"Message delivery timed out",[n.INVALID_CONFIG]:"Invalid configuration",[n.MISSING_API_KEY]:"API key is missing",[n.MISSING_SERVER_URL]:"Server URL is missing",[n.INVALID_CREDENTIALS]:"Invalid MQTT credentials",[n.REGISTRATION_FAILED]:"Device registration failed",[n.DEVICE_ID_GENERATION_FAILED]:"Failed to generate device ID",[n.SERVER_ERROR]:"Server returned an error",[n.NETWORK_ERROR]:"Network request failed",[n.NOT_INITIALIZED]:"SDK is not initialized",[n.NOT_CONNECTED]:"Not connected to server",[n.ALREADY_CONNECTED]:"Already connected to server",[n.SERVICE_NOT_RUNNING]:"Service worker is not running",[n.PERMISSION_DENIED]:"Notification permission denied",[n.PERMISSION_DISMISSED]:"Notification permission dismissed",[n.UNKNOWN_ERROR]:"An unknown error occurred"};class o extends Error{constructor(e,t){super(s[e]||"Unknown error"),this.name="RiviumPushError",this.code=e,this.details=t}toJSON(){return{code:this.code,message:this.message,details:this.details}}}var a,r,c;!function(e){e.SDK_INITIALIZED="sdkInitialized",e.DEVICE_REGISTERED="deviceRegistered",e.DEVICE_UNREGISTERED="deviceUnregistered",e.MESSAGE_RECEIVED="messageReceived",e.MESSAGE_DISPLAYED="messageDisplayed",e.NOTIFICATION_CLICKED="notificationClicked",e.ACTION_CLICKED="actionClicked",e.CONNECTED="connected",e.DISCONNECTED="disconnected",e.CONNECTION_ERROR="connectionError",e.RETRY_STARTED="retryStarted",e.TOPIC_SUBSCRIBED="topicSubscribed",e.TOPIC_UNSUBSCRIBED="topicUnsubscribed",e.NETWORK_STATE_CHANGED="networkStateChanged",e.APP_STATE_CHANGED="appStateChanged",e.PERMISSION_REQUESTED="permissionRequested",e.PERMISSION_GRANTED="permissionGranted",e.PERMISSION_DENIED="permissionDenied"}(a||(a={})),function(e){e[e.NONE=0]="NONE",e[e.ERROR=1]="ERROR",e[e.WARNING=2]="WARNING",e[e.INFO=3]="INFO",e[e.DEBUG=4]="DEBUG",e[e.VERBOSE=5]="VERBOSE"}(r||(r={})),function(e){e.WIFI="wifi",e.CELLULAR="cellular",e.ETHERNET="ethernet",e.NONE="none",e.UNKNOWN="unknown"}(c||(c={}));const l="https://push-api.rivium.co";class h{constructor(e){var t;if(this.deviceId=null,this.pnSocket=null,this.serviceWorkerRegistration=null,this.pushSubscription=null,this.connectionState="disconnected",this.reconnectAttempts=0,this.maxReconnectAttempts=10,this.reconnectTimer=null,this.subscribedTopics=new Set,this.badgeCount=0,this.initialized=!1,this.initialMessage=null,this.mqttConfig=null,this.mqttConfigFetched=!1,this.appId=null,this.appIdentifier=null,this.vapidPublicKey=null,this.logLevel=r.DEBUG,this.analyticsCallback=null,this.analyticsEnabled=!1,this.onMessageCallback=null,this.onConnectionStateCallback=null,this.onRegisteredCallback=null,this.onErrorCallback=null,this.onDetailedErrorCallback=null,this.onNotificationClickCallback=null,this.onActionClickedCallback=null,this.onReconnectingCallback=null,this.onNetworkStateCallback=null,this.onAppStateCallback=null,!e.apiKey)throw new Error("RiviumPush: apiKey is required");this.config={serviceWorkerPath:"/rivium-push-sw.js",autoRegisterServiceWorker:!0,mqttQos:1,maxReconnectAttempts:10,logLevel:r.ERROR,...e},this.maxReconnectAttempts=this.config.maxReconnectAttempts,this.logLevel=this.config.logLevel,"undefined"!=typeof window?(this.deviceId=this.getOrCreateDeviceId(),this.badgeCount=parseInt(localStorage.getItem("rivium_push_badge_count")||"0",10),this.checkInitialMessage(),"serviceWorker"in navigator&&navigator.serviceWorker.addEventListener("message",this.handleServiceWorkerMessage.bind(this)),document.addEventListener("visibilitychange",this.handleVisibilityChange.bind(this)),"connection"in navigator&&(null===(t=navigator.connection)||void 0===t||t.addEventListener("change",this.handleNetworkChange.bind(this))),window.addEventListener("online",this.handleOnline.bind(this)),window.addEventListener("offline",this.handleOffline.bind(this)),this.initialized=!0,this.trackEvent(a.SDK_INITIALIZED),this.log(r.INFO,"RiviumPush SDK initialized"),this.fetchMqttConfig()):this.initialized=!0}async fetchMqttConfig(){try{this.log(r.DEBUG,"Fetching config from server...");const e=await fetch(`${l}/devices/config`,{method:"GET",headers:{"Content-Type":"application/json","x-api-key":this.config.apiKey}});if(!e.ok)throw new Error(`HTTP ${e.status}`);const t=await e.json();this.mqttConfig=t.mqtt,this.mqttConfigFetched=!0,t.vapidPublicKey&&(this.vapidPublicKey=t.vapidPublicKey,this.log(r.DEBUG,"VAPID public key received from server")),this.log(r.INFO,`Config fetched successfully, vapid=${!!this.vapidPublicKey}`)}catch(e){this.log(r.ERROR,"Failed to fetch config:",e),this.emitError(n.INVALID_CONFIG,`Failed to fetch config: ${e.message}`)}}log(e,t,...i){if(e>this.logLevel)return;const n="[RiviumPush]";switch(e){case r.ERROR:console.error(n,t,...i);break;case r.WARNING:console.warn(n,t,...i);break;case r.INFO:console.info(n,t,...i);break;case r.DEBUG:case r.VERBOSE:console.log(n,t,...i)}}setLogLevel(e){this.logLevel=e,this.log(r.INFO,`Log level set to ${r[e]}`)}getLogLevel(){return this.logLevel}trackEvent(e,t){if(this.analyticsEnabled&&this.analyticsCallback)try{this.analyticsCallback(e,t)}catch(e){this.log(r.ERROR,"Analytics callback error:",e)}this.log(r.VERBOSE,`Analytics event: ${e}`,t)}setAnalyticsHandler(e){this.analyticsCallback=e,this.analyticsEnabled=!0,this.log(r.INFO,"Analytics handler set")}disableAnalytics(){this.analyticsCallback=null,this.analyticsEnabled=!1,this.log(r.INFO,"Analytics disabled")}isAnalyticsEnabled(){return this.analyticsEnabled}emitError(e,t){const i=new o(e,t);this.log(r.ERROR,`Error [${e}]: ${i.message}`,t),this.onDetailedErrorCallback&&this.onDetailedErrorCallback(i),this.onErrorCallback&&this.onErrorCallback(i),this.trackEvent(a.CONNECTION_ERROR,{errorCode:e,errorMessage:i.message,details:t})}async register(e){try{this.mqttConfigFetched||(this.log(r.DEBUG,"Waiting for server config..."),await this.waitForConfig()),this.config.autoRegisterServiceWorker&&await this.registerServiceWorker(),this.trackEvent(a.PERMISSION_REQUESTED);const t=await this.requestNotificationPermission();if("denied"===t)throw this.trackEvent(a.PERMISSION_DENIED),this.emitError(n.PERMISSION_DENIED),new o(n.PERMISSION_DENIED);if("default"===t)throw this.trackEvent(a.PERMISSION_DENIED),this.emitError(n.PERMISSION_DISMISSED,"User dismissed the permission prompt"),new o(n.PERMISSION_DISMISSED);this.trackEvent(a.PERMISSION_GRANTED);const i=this.vapidPublicKey||this.config.vapidPublicKey;if(i&&this.serviceWorkerRegistration)try{this.pushSubscription=await this.subscribeToPush(i),this.log(r.INFO,"Web Push subscription created for background notifications")}catch(e){this.log(r.WARNING,"Web Push subscription failed (will use MQTT only):",e)}const s=await this.registerDevice(e);return this.deviceId=s.deviceId,this.connectToGateway(),this.onRegisteredCallback&&this.onRegisteredCallback(s.deviceId),this.trackEvent(a.DEVICE_REGISTERED,{deviceId:s.deviceId,userId:null==e?void 0:e.userId,hasWebPush:!!this.pushSubscription}),this.log(r.INFO,"Registered with device ID:",s.deviceId,"Web Push:",!!this.pushSubscription),s.deviceId}catch(e){if(e instanceof o)throw e;throw this.log(r.ERROR,"Registration failed:",e),this.emitError(n.REGISTRATION_FAILED,e.message),e}}async waitForConfig(e=5e3){const t=Date.now();for(;!this.mqttConfigFetched&&Date.now()-t<e;)await new Promise(e=>setTimeout(e,100));this.mqttConfigFetched||this.log(r.WARNING,"Config fetch timed out, continuing without it")}async unregister(){this.disconnectFromGateway(),this.pushSubscription&&(await this.pushSubscription.unsubscribe(),this.pushSubscription=null),this.trackEvent(a.DEVICE_UNREGISTERED,{deviceId:this.deviceId}),this.log(r.INFO,"Unregistered")}async subscribeTopic(e){if(e&&""!==e.trim()){if(this.subscribedTopics.add(e),this.deviceId)try{await fetch(`${l}/topics/subscribe`,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":this.config.apiKey},body:JSON.stringify({deviceId:this.deviceId,topic:e})})}catch(e){this.log(r.WARNING,"Failed to register topic on server:",e)}if(this.pnSocket&&this.pnSocket.isConnected()){const t=`rivium_push/${this.config.apiKey.substring(0,16)}/topic/${e}`;this.pnSocket.stream(t,e=>{this.handlePNMessage(e)},this.config.mqttQos),this.log(r.INFO,"Subscribed to topic:",e),this.trackEvent(a.TOPIC_SUBSCRIBED,{topic:e})}}else this.emitError(n.INVALID_TOPIC,"Topic cannot be empty")}async unsubscribeTopic(e){if(this.subscribedTopics.delete(e),this.deviceId)try{await fetch(`${l}/topics/unsubscribe`,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":this.config.apiKey},body:JSON.stringify({deviceId:this.deviceId,topic:e})})}catch(e){this.log(r.WARNING,"Failed to unregister topic on server:",e)}if(this.pnSocket&&this.pnSocket.isConnected()){const t=`rivium_push/${this.config.apiKey.substring(0,16)}/topic/${e}`;this.pnSocket.detach(t),this.log(r.INFO,"Unsubscribed from topic:",e),this.trackEvent(a.TOPIC_UNSUBSCRIBED,{topic:e})}}isConnected(){return"connected"===this.connectionState}getDeviceId(){return this.deviceId}async setUserId(e){localStorage.setItem("rivium_push_user_id",e),await this.registerDevice({userId:e}),this.log(r.INFO,"User ID set:",e)}clearUserId(){localStorage.removeItem("rivium_push_user_id"),this.log(r.INFO,"User ID cleared")}getInitialMessage(){return this.initialMessage}getBadgeCount(){return this.badgeCount}setBadgeCount(e){this.badgeCount=Math.max(0,e),localStorage.setItem("rivium_push_badge_count",this.badgeCount.toString()),this.updateFaviconBadge(this.badgeCount),"setAppBadge"in navigator&&(this.badgeCount>0?navigator.setAppBadge(this.badgeCount):navigator.clearAppBadge())}clearBadge(){this.setBadgeCount(0)}async refreshMqttToken(){if(!this.deviceId)throw new o(n.NOT_INITIALIZED,"Device not registered");try{const e=await fetch(`${l}/devices/${this.deviceId}/mqtt-token/refresh`,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":this.config.apiKey}});if(!e.ok){const t=await e.json().catch(()=>({}));throw new o(n.SERVER_ERROR,t.message||`HTTP ${e.status}`)}const t=await e.json();t.token&&this.mqttConfig&&(this.mqttConfig.token=t.token,this.log(r.INFO,"MQTT token refreshed successfully"))}catch(e){if(e instanceof o)throw e;throw new o(n.NETWORK_ERROR,e.message)}}getNetworkState(){const e=navigator.connection;return{isAvailable:navigator.onLine,networkType:this.detectNetworkType(),effectiveType:null==e?void 0:e.effectiveType,downlink:null==e?void 0:e.downlink,rtt:null==e?void 0:e.rtt}}getAppState(){return{isVisible:"visible"===document.visibilityState,visibilityState:document.visibilityState}}static isSupported(){return"undefined"!=typeof window&&"Notification"in window&&"serviceWorker"in navigator}static getPermissionStatus(){return"undefined"==typeof Notification?"denied":Notification.permission}onMessage(e){return this.onMessageCallback=e,()=>{this.onMessageCallback=null}}onConnectionState(e){return this.onConnectionStateCallback=e,()=>{this.onConnectionStateCallback=null}}onRegistered(e){return this.onRegisteredCallback=e,()=>{this.onRegisteredCallback=null}}onError(e){return this.onErrorCallback=e,()=>{this.onErrorCallback=null}}onDetailedError(e){return this.onDetailedErrorCallback=e,()=>{this.onDetailedErrorCallback=null}}onNotificationClick(e){return this.onNotificationClickCallback=e,()=>{this.onNotificationClickCallback=null}}onActionClicked(e){return this.onActionClickedCallback=e,()=>{this.onActionClickedCallback=null}}onReconnecting(e){return this.onReconnectingCallback=e,()=>{this.onReconnectingCallback=null}}onNetworkState(e){return this.onNetworkStateCallback=e,()=>{this.onNetworkStateCallback=null}}onAppState(e){return this.onAppStateCallback=e,()=>{this.onAppStateCallback=null}}detectNetworkType(){const e=navigator.connection;if(!e)return c.UNKNOWN;switch(e.type){case"wifi":return c.WIFI;case"cellular":return c.CELLULAR;case"ethernet":return c.ETHERNET;case"none":return c.NONE;default:return c.UNKNOWN}}handleNetworkChange(){const e=this.getNetworkState();this.log(r.DEBUG,"Network state changed:",e),this.onNetworkStateCallback&&this.onNetworkStateCallback(e),this.trackEvent(a.NETWORK_STATE_CHANGED,{isAvailable:e.isAvailable,networkType:e.networkType,effectiveType:e.effectiveType})}handleOnline(){this.log(r.INFO,"Network online"),this.handleNetworkChange(),"disconnected"===this.connectionState&&this.deviceId&&(this.log(r.INFO,"Reconnecting after network restored"),this.connectToGateway())}handleOffline(){this.log(r.INFO,"Network offline"),this.handleNetworkChange()}handleVisibilityChange(){const e=this.getAppState();this.log(r.DEBUG,"App state changed:",e),this.onAppStateCallback&&this.onAppStateCallback(e),this.trackEvent(a.APP_STATE_CHANGED,{isVisible:e.isVisible,visibilityState:e.visibilityState}),e.isVisible&&"disconnected"===this.connectionState&&this.deviceId&&(this.log(r.INFO,"Reconnecting after becoming visible"),this.connectToGateway())}checkInitialMessage(){if("undefined"!=typeof window){const e=new URLSearchParams(window.location.search).get("rivium_push_notification");if(e)try{this.initialMessage=JSON.parse(decodeURIComponent(e)),this.log(r.INFO,"Initial message found:",this.initialMessage)}catch(e){this.log(r.WARNING,"Failed to parse initial message:",e)}const t=sessionStorage.getItem("rivium_push_initial_message");if(t&&!this.initialMessage)try{this.initialMessage=JSON.parse(t),sessionStorage.removeItem("rivium_push_initial_message"),this.log(r.INFO,"Initial message from session:",this.initialMessage)}catch(e){this.log(r.WARNING,"Failed to parse stored message:",e)}}}async registerServiceWorker(){if(!("serviceWorker"in navigator))throw new o(n.SERVICE_NOT_RUNNING,"Service Workers not supported");try{this.serviceWorkerRegistration=await navigator.serviceWorker.register(this.config.serviceWorkerPath,{scope:"/"}),this.log(r.INFO,"Service Worker registered")}catch(e){throw this.log(r.ERROR,"Service Worker registration failed:",e),new o(n.SERVICE_NOT_RUNNING,e.message)}}async requestNotificationPermission(){return"undefined"==typeof Notification?"denied":"granted"===Notification.permission?"granted":await Notification.requestPermission()}async subscribeToPush(e){if(!this.serviceWorkerRegistration)throw new o(n.SERVICE_NOT_RUNNING,"Service Worker not registered");const t=await this.serviceWorkerRegistration.pushManager.getSubscription();if(t)return this.log(r.DEBUG,"Using existing Push subscription"),t;const i=await this.serviceWorkerRegistration.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:this.urlBase64ToUint8Array(e)});return this.log(r.INFO,"Push subscription created"),i}async registerDevice(e){var t,i,s;try{const a={deviceId:this.deviceId,platform:"web",userId:null==e?void 0:e.userId,appIdentifier:"undefined"!=typeof window?window.location.origin:void 0,metadata:{...null==e?void 0:e.metadata,userAgent:navigator.userAgent,language:navigator.language,url:window.location.origin}};if(this.pushSubscription){const e=this.pushSubscription.toJSON();a.webPushSubscription={endpoint:e.endpoint,keys:{p256dh:(null===(t=e.keys)||void 0===t?void 0:t.p256dh)||"",auth:(null===(i=e.keys)||void 0===i?void 0:i.auth)||""}},this.log(r.DEBUG,"Sending Web Push subscription to server")}const c=await fetch(`${l}/devices/register`,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":this.config.apiKey},body:JSON.stringify(a)});if(!c.ok){const e=await c.json().catch(()=>({}));throw new o(n.SERVER_ERROR,e.message||`HTTP ${c.status}`)}const h=await c.json();return h.appId&&(this.appId=h.appId),h.appIdentifier&&(this.appIdentifier=h.appIdentifier),(null===(s=h.mqtt)||void 0===s?void 0:s.token)&&this.mqttConfig&&(this.mqttConfig.token=h.mqtt.token,this.log(r.DEBUG,"Connection token received from registration")),h}catch(e){if(e instanceof o)throw e;throw new o(n.NETWORK_ERROR,e.message)}}connectToGateway(){if(this.pnSocket&&this.pnSocket.close(),this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),!this.mqttConfig)return this.log(r.WARNING,"Gateway config not available, retrying in 2s..."),void setTimeout(()=>this.connectToGateway(),2e3);if(!this.mqttConfig.token)return this.log(r.ERROR,"Connection token not available. Device must be registered first."),void this.emitError(n.AUTHENTICATION_FAILED,"Connection token not available");this.setConnectionState("connecting");const s=this.mqttConfig.wsHost||this.mqttConfig.host,o=this.mqttConfig.wsPort,c="undefined"!=typeof window&&"https:"===window.location.protocol||443===o;this.log(r.DEBUG,`Connecting to gateway (secure: ${c})`);const l=`rivium_push_${this.appId}_${this.deviceId}`,h=(new e).gateway(s).port(o).clientId(l).auth(t.token(this.mqttConfig.token)).secure(c).freshStart(!1).autoReconnect(!1).connectionTimeout(10).build();this.pnSocket=new i(h);const d={onStateChanged:e=>{this.log(r.DEBUG,`Connection state changed: ${e}`)},onConnected:()=>{this.log(r.INFO,"Connected to gateway"),this.setConnectionState("connected"),this.reconnectAttempts=0,this.trackEvent(a.CONNECTED);const e=this.config.apiKey.substring(0,16),t=this.appIdentifier||("undefined"!=typeof window?window.location.origin:"_default"),i=`rivium_push/${e}/${this.deviceId}/${t}`;this.pnSocket.stream(i,e=>{this.handlePNMessage(e)},this.config.mqttQos),this.log(r.DEBUG,"Streaming from device channel");const n=`rivium_push/${e}/broadcast`;this.pnSocket.stream(n,e=>{this.handlePNMessage(e)},this.config.mqttQos),this.log(r.DEBUG,"Streaming from broadcast channel"),this.subscribedTopics.forEach(t=>{const i=`rivium_push/${e}/topic/${t}`;this.pnSocket.stream(i,e=>{this.handlePNMessage(e)},this.config.mqttQos)})},onDisconnected:e=>{this.log(r.INFO,"Disconnected from gateway",e||""),this.setConnectionState("disconnected"),this.trackEvent(a.DISCONNECTED),this.scheduleReconnect()},onReconnecting:(e,t)=>{this.log(r.INFO,`Reconnecting attempt ${e} in ${t}ms`)}};this.pnSocket.addConnectionListener(d),this.pnSocket.addErrorListener(e=>{this.log(r.ERROR,"Gateway error:",e.message),this.setConnectionState("error");let t=n.CONNECTION_FAILED;const i=e.message.toLowerCase();if(i.includes("timeout"))t=n.CONNECTION_TIMEOUT;else if(i.includes("refused")||i.includes("not authorized")){if(t=n.CONNECTION_REFUSED,i.includes("not authorized"))return this.log(r.INFO,"Token may be expired, attempting refresh..."),void this.refreshMqttToken().then(()=>{this.log(r.INFO,"Token refreshed, reconnecting..."),this.connectToGateway()}).catch(e=>{this.log(r.ERROR,"Token refresh failed:",e),this.emitError(n.AUTHENTICATION_FAILED,"Token expired and refresh failed")})}else i.includes("auth")||i.includes("credential")?t=n.AUTHENTICATION_FAILED:(i.includes("ssl")||i.includes("tls"))&&(t=n.SSL_ERROR);this.emitError(t,e.message)}),this.log(r.DEBUG,"Opening connection to gateway..."),this.pnSocket.open()}handlePNMessage(e){try{const t=e.payloadAsJson();this.handleMqttMessage(e.channel,t)}catch(e){this.log(r.ERROR,"Message parse error:",e),this.emitError(n.MESSAGE_PARSE_ERROR,e.message)}}disconnectFromGateway(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.pnSocket&&(this.pnSocket.close(),this.pnSocket=null),this.setConnectionState("disconnected")}scheduleReconnect(){if(this.reconnectAttempts>=this.maxReconnectAttempts)return this.log(r.WARNING,"Max reconnect attempts reached"),void this.emitError(n.CONNECTION_FAILED,"Max reconnect attempts reached");if(!navigator.onLine)return void this.log(r.DEBUG,"Offline, skipping reconnect");const e=Math.min(1e3*Math.pow(2,this.reconnectAttempts),3e4);this.reconnectAttempts++,this.log(r.INFO,`Reconnecting in ${e}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);const t={retryAttempt:this.reconnectAttempts,nextRetryMs:e,maxRetryAttempts:this.maxReconnectAttempts};this.onReconnectingCallback&&this.onReconnectingCallback(t),this.trackEvent(a.RETRY_STARTED,{retryAttempt:this.reconnectAttempts,nextRetryMs:e}),this.reconnectTimer=setTimeout(()=>{this.connectToGateway()},e)}handleMqttMessage(e,t){var i;const n=this.normalizeMessage(t);this.log(r.DEBUG,"Message received:",n.title),this.trackEvent(a.MESSAGE_RECEIVED,{messageId:n.messageId,title:n.title,silent:n.silent,hasImage:!!n.imageUrl,hasActions:!!(null===(i=n.actions)||void 0===i?void 0:i.length)}),this.handleBadge(n),n.silent||"visible"===document.visibilityState||(this.showRichNotification(n),this.trackEvent(a.MESSAGE_DISPLAYED,{messageId:n.messageId,title:n.title})),this.onMessageCallback&&this.onMessageCallback(n)}normalizeMessage(e){const t=this.getLocalizedContent(e,"title"),i=this.getLocalizedContent(e,"body");return{title:t||e.title||"",body:i||e.body||"",data:e.data,silent:e.silent,imageUrl:e.imageUrl||e.image,iconUrl:e.iconUrl||e.icon,actions:e.actions,deepLink:e.deepLink,badge:e.badge,badgeAction:e.badgeAction,sound:e.sound,threadId:e.threadId,collapseKey:e.collapseKey,category:e.category,priority:e.priority,ttl:e.ttl,localizations:e.localizations,timezone:e.timezone,messageId:e.messageId,campaignId:e.campaignId,icon:e.iconUrl||e.icon,image:e.imageUrl||e.image,tag:e.tag||e.collapseKey||e.threadId}}getLocalizedContent(e,t){if(!e.localizations||!Array.isArray(e.localizations))return null;const i=navigator.language.split("-")[0].toLowerCase(),n=e.localizations.find(e=>e.locale.toLowerCase().startsWith(i));return n?n[t]:null}handleBadge(e){if(void 0===e.badge&&!e.badgeAction)return;const t=e.badgeAction||"set";let i=e.badge||0;switch(t){case"set":i=e.badge||0;break;case"increment":i=this.badgeCount+(e.badge||1);break;case"decrement":i=Math.max(0,this.badgeCount-(e.badge||1));break;case"clear":i=0}this.setBadgeCount(i)}handleServiceWorkerMessage(e){var t;const i=e.data;if("push-message"===i.type){this.log(r.DEBUG,"Push message received from SW:",null===(t=i.message)||void 0===t?void 0:t.title);const e=this.normalizeMessage(i.message);this.trackEvent(a.MESSAGE_RECEIVED,{messageId:e.messageId,title:e.title,source:"web-push"}),this.handleBadge(e),this.onMessageCallback&&this.onMessageCallback(e)}else if("notification-click"===i.type){this.log(r.INFO,"Notification clicked from SW");const e=this.normalizeMessage(i.message||{});this.trackEvent(a.NOTIFICATION_CLICKED,{messageId:e.messageId,title:e.title,action:i.action}),this.onNotificationClickCallback&&this.onNotificationClickCallback(e,i.action)}else if("action-clicked"===i.type){this.log(r.INFO,"Action clicked from SW:",i.actionId);const e=this.normalizeMessage(i.message||{});this.trackEvent(a.ACTION_CLICKED,{actionId:i.actionId,messageId:e.messageId,title:e.title}),this.onActionClickedCallback&&this.onActionClickedCallback(i.actionId,e)}else"initial-message"===i.type?(this.log(r.INFO,"Initial message received from SW"),this.initialMessage=this.normalizeMessage(i.message||{}),this.onNotificationClickCallback&&this.initialMessage&&this.onNotificationClickCallback(this.initialMessage,void 0)):"navigate"===i.type&&(this.log(r.INFO,"Navigating to:",i.url),i.url&&"undefined"!=typeof window&&(window.location.href=i.url))}showRichNotification(e){if("granted"!==Notification.permission)return;const t={body:e.body,icon:e.iconUrl||e.icon,badge:e.iconUrl||e.icon,image:e.imageUrl||e.image,tag:e.tag||e.collapseKey||e.threadId,data:{...e.data,deepLink:e.deepLink,messageId:e.messageId,campaignId:e.campaignId,riviumPushMessage:e},requireInteraction:"high"===e.priority,silent:"none"===e.sound};if(e.actions&&e.actions.length>0){const i=e.actions.slice(0,2).map(e=>({action:e.id,title:e.title,icon:e.icon}));this.serviceWorkerRegistration&&(t.actions=i)}if(this.serviceWorkerRegistration)this.serviceWorkerRegistration.showNotification(e.title,t);else{const i=new Notification(e.title,t);i.onclick=()=>{window.focus(),e.deepLink&&(window.location.href=e.deepLink),this.onNotificationClickCallback&&this.onNotificationClickCallback(e),this.trackEvent(a.NOTIFICATION_CLICKED,{messageId:e.messageId,title:e.title}),i.close()}}}updateFaviconBadge(e){try{const t=document.createElement("canvas"),i=t.getContext("2d");if(!i)return;const n=32;t.width=n,t.height=n;const s=document.querySelector('link[rel="icon"]'),o=(null==s?void 0:s.href)||"/favicon.ico",a=new Image;a.crossOrigin="anonymous",a.onload=()=>{if(i.drawImage(a,0,0,n,n),e>0){const t=14,s=n-t/2,o=t/2;i.beginPath(),i.arc(s,o,t/2+1,0,2*Math.PI),i.fillStyle="#ef4444",i.fill(),i.fillStyle="#ffffff",i.font="bold 10px sans-serif",i.textAlign="center",i.textBaseline="middle",i.fillText(e>99?"99+":e.toString(),s,o)}const o=document.createElement("link");o.rel="icon",o.href=t.toDataURL("image/png"),s&&s.remove(),document.head.appendChild(o)},a.src=o}catch(e){this.log(r.WARNING,"Could not update favicon badge:",e)}}setConnectionState(e){this.connectionState=e,this.onConnectionStateCallback&&this.onConnectionStateCallback(e)}getOrCreateDeviceId(){const e="rivium_push_device_id";let t=localStorage.getItem(e);return t||(t="web_"+this.generateUUID(),localStorage.setItem(e,t)),t}generateUUID(){return"undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}urlBase64ToUint8Array(e){const t=(e+"=".repeat((4-e.length%4)%4)).replace(/-/g,"+").replace(/_/g,"/"),i=window.atob(t),n=new Uint8Array(i.length);for(let e=0;e<i.length;++e)n[e]=i.charCodeAt(e);return n}}export{c as NetworkType,h as RiviumPush,a as RiviumPushAnalyticsEvent,o as RiviumPushError,n as RiviumPushErrorCode,r as RiviumPushLogLevel,h as default};
2
+ //# sourceMappingURL=index.esm.js.map