@@ -7,17 +7,24 @@ export interface PusherConfig {
77 csrfToken : string ;
88}
99
10+ export interface EventBinding {
11+ eventName : string ;
12+ onEvent : ( ) => void ;
13+ }
14+
1015export interface SubscriptionConfig {
1116 channelName : string ;
12- eventName : string ;
13- onEvent : ( data : unknown ) => void ;
17+ eventBindings : EventBinding [ ] ;
1418 onError ?: ( error : Error ) => void ;
1519}
1620
1721export class PusherListener {
1822 private pusher : Pusher ;
1923 private currentChannel : Channel | null = null ;
20- private currentSubscription : SubscriptionConfig | null = null ;
24+ private currentChannelName : string | null = null ;
25+ private eventHandlersMap : Map < string , ( ) => void > = new Map ( ) ;
26+ private globalCallback : ( ( eventName : string , data : unknown ) => void ) | null = null ;
27+ private onError ?: ( error : Error ) => void ;
2128
2229 constructor ( private config : PusherConfig ) {
2330 this . pusher = new Pusher ( this . config . key , {
@@ -36,46 +43,59 @@ export class PusherListener {
3643 }
3744
3845 /**
39- * Subscribe to channel for specific object and event
40- * Automatically unsubscribes from previous channel if different
46+ * Subscribe to channel for specific object and bind multiple events
47+ * Only resubscribes when channel name changes, not when handlers change
4148 */
4249 subscribe ( config : SubscriptionConfig ) : void {
43- // If already subscribed to same channel and event, do nothing
44- if ( config === this . currentSubscription ) {
45- return ;
46- }
50+ // Only resubscribe if channel name changes
51+ if ( config . channelName !== this . currentChannelName ) {
52+ this . unsubscribe ( ) ;
53+ this . currentChannelName = config . channelName ;
54+ this . currentChannel = this . pusher . subscribe ( config . channelName ) ;
4755
48- // Unsubscribe from previous channel if exists
49- this . unsubscribe ( ) ;
50-
51- // Subscribe to new channel
52- this . currentSubscription = config ;
53- this . currentChannel = this . pusher . subscribe ( config . channelName ) ;
56+ // Setup global handler once per channel
57+ this . globalCallback = ( eventName : string , _data : unknown ) => {
58+ const handler = this . eventHandlersMap . get ( eventName ) ;
59+ if ( handler ) {
60+ handler ( ) ;
61+ }
62+ } ;
63+ this . currentChannel . bind_global ( this . globalCallback ) ;
5464
55- // Bind event handler
56- this . currentChannel . bind ( config . eventName , config . onEvent ) ;
65+ // Bind error handler
66+ this . currentChannel . bind ( "pusher:subscription_error" , ( error : unknown ) => {
67+ console . error ( error ) ;
68+ const errorMsg =
69+ error === 515
70+ ? "Authentication failed. Please verify Pusher configuration constants."
71+ : `Subscription error: ${ String ( error ) } ` ;
72+ this . onError ?.( new Error ( errorMsg ) ) ;
73+ } ) ;
74+ }
5775
58- // Bind error handler
59- this . currentChannel . bind ( "pusher:subscription_error" , ( error : unknown ) => {
60- console . error ( error ) ;
61- const errorMsg =
62- error === 515
63- ? "Authentication failed. Please verify Pusher configuration constants."
64- : `Subscription error: ${ String ( error ) } ` ;
65- config . onError ?.( new Error ( errorMsg ) ) ;
76+ // Always update handler map (no rebinding needed)
77+ this . eventHandlersMap . clear ( ) ;
78+ config . eventBindings . forEach ( binding => {
79+ this . eventHandlersMap . set ( binding . eventName , binding . onEvent ) ;
6680 } ) ;
81+
82+ // Store error handler for reference
83+ this . onError = config . onError ;
6784 }
6885
6986 /**
7087 * Unsubscribe from current channel
7188 */
7289 unsubscribe ( ) : void {
73- if ( this . currentChannel && this . currentSubscription ) {
74- // Unbind all channel events
75- this . currentChannel . unbind ( ) ;
76- this . pusher . unsubscribe ( this . currentSubscription . channelName ) ;
90+ if ( this . currentChannel && this . currentChannelName ) {
91+ // Unbind all channel events (both global and specific)
92+ this . currentChannel . unbind_all ( ) ;
93+ this . pusher . unsubscribe ( this . currentChannelName ) ;
7794 this . currentChannel = null ;
78- this . currentSubscription = null ;
95+ this . currentChannelName = null ;
96+ this . globalCallback = null ;
97+ this . eventHandlersMap . clear ( ) ;
98+ this . onError = undefined ;
7999 }
80100 }
81101
0 commit comments