@@ -14,6 +14,7 @@ import ConnectionManager from '../transport/connectionmanager';
14
14
import ConnectionStateChange from './connectionstatechange' ;
15
15
import { ErrCallback , PaginatedResultCallback , StandardCallback } from '../../types/utils' ;
16
16
import BaseRealtime from './baserealtime' ;
17
+ import { FilteredSubscriptions } from './filteredsubscriptions' ;
17
18
18
19
interface RealtimeHistoryParams {
19
20
start ?: number ;
@@ -438,121 +439,22 @@ class RealtimeChannel extends Channel {
438
439
439
440
// Filtered
440
441
if ( event && typeof event === 'object' && ! Array . isArray ( event ) ) {
441
- this . _subscribeFilter ( event , listener ) ;
442
+ FilteredSubscriptions . subscribeFilter ( this , event , listener ) ;
442
443
} else {
443
444
this . subscriptions . on ( event , listener ) ;
444
445
}
445
446
446
447
return this . attach ( callback || noop ) ;
447
448
}
448
449
449
- _subscribeFilter ( filter : API . Types . MessageFilter , listener : API . Types . messageCallback < Message > ) {
450
- const filteredListener = ( m : Message ) => {
451
- const mapping : { [ key in keyof API . Types . MessageFilter ] : any } = {
452
- name : m . name ,
453
- refTimeserial : m . extras ?. ref ?. timeserial ,
454
- refType : m . extras ?. ref ?. type ,
455
- isRef : ! ! m . extras ?. ref ?. timeserial ,
456
- clientId : m . clientId ,
457
- } ;
458
- // Check if any values are defined in the filter and if they match the value in the message object
459
- if (
460
- Object . entries ( filter ) . find ( ( [ key , value ] ) =>
461
- value !== undefined ? mapping [ key as keyof API . Types . MessageFilter ] !== value : false
462
- )
463
- ) {
464
- return ;
465
- }
466
- listener ( m ) ;
467
- } ;
468
- this . _addFilteredSubscription ( filter , listener , filteredListener ) ;
469
- this . subscriptions . on ( filteredListener ) ;
470
- }
471
-
472
- // Adds a new filtered subscription
473
- _addFilteredSubscription (
474
- filter : API . Types . MessageFilter ,
475
- realListener : API . Types . messageCallback < Message > ,
476
- filteredListener : API . Types . messageCallback < Message >
477
- ) {
478
- if ( ! this . filteredSubscriptions ) {
479
- this . filteredSubscriptions = new Map <
480
- API . Types . messageCallback < Message > ,
481
- Map < API . Types . MessageFilter , API . Types . messageCallback < Message > [ ] >
482
- > ( ) ;
483
- }
484
- if ( this . filteredSubscriptions . has ( realListener ) ) {
485
- const realListenerMap = this . filteredSubscriptions . get ( realListener ) as Map <
486
- API . Types . MessageFilter ,
487
- API . Types . messageCallback < Message > [ ]
488
- > ;
489
- // Add the filtered listener to the map, or append to the array if this filter has already been used
490
- realListenerMap . set ( filter , realListenerMap ?. get ( filter ) ?. concat ( filteredListener ) || [ filteredListener ] ) ;
491
- } else {
492
- this . filteredSubscriptions . set (
493
- realListener ,
494
- new Map < API . Types . MessageFilter , API . Types . messageCallback < Message > [ ] > ( [ [ filter , [ filteredListener ] ] ] )
495
- ) ;
496
- }
497
- }
498
-
499
- _getAndDeleteFilteredSubscriptions (
500
- filter : API . Types . MessageFilter | undefined ,
501
- realListener : API . Types . messageCallback < Message > | undefined
502
- ) : API . Types . messageCallback < Message > [ ] {
503
- // No filtered subscriptions map means there has been no filtered subscriptions yet, so return nothing
504
- if ( ! this . filteredSubscriptions ) {
505
- return [ ] ;
506
- }
507
- // Only a filter is passed in with no specific listener
508
- if ( ! realListener && filter ) {
509
- // Return each listener which is attached to the specified filter object
510
- return Array . from ( this . filteredSubscriptions . entries ( ) )
511
- . map ( ( [ key , filterMaps ] ) => {
512
- // Get (then delete) the maps matching this filter
513
- let listenerMaps = filterMaps . get ( filter ) ;
514
- filterMaps . delete ( filter ) ;
515
- // Clear the parent if nothing is left
516
- if ( filterMaps . size === 0 ) {
517
- this . filteredSubscriptions ?. delete ( key ) ;
518
- }
519
- return listenerMaps ;
520
- } )
521
- . reduce (
522
- ( prev , cur ) => ( cur ? ( prev as API . Types . messageCallback < Message > [ ] ) . concat ( ...cur ) : prev ) ,
523
- [ ]
524
- ) as API . Types . messageCallback < Message > [ ] ;
525
- }
526
-
527
- // No subscriptions for this listener
528
- if ( ! realListener || ! this . filteredSubscriptions . has ( realListener ) ) {
529
- return [ ] ;
530
- }
531
- const realListenerMap = this . filteredSubscriptions . get ( realListener ) as Map <
532
- API . Types . MessageFilter ,
533
- API . Types . messageCallback < Message > [ ]
534
- > ;
535
- // If no filter is specified return all listeners using that function
536
- if ( ! filter ) {
537
- // array.flat is not available unless we support es2019 or higher
538
- const listeners = Array . from ( realListenerMap . values ( ) ) . reduce ( ( prev , cur ) => prev . concat ( ...cur ) , [ ] ) ;
539
- // remove the listener from the map
540
- this . filteredSubscriptions . delete ( realListener ) ;
541
- return listeners ;
542
- }
543
-
544
- let listeners = realListenerMap . get ( filter ) ;
545
- realListenerMap . delete ( filter ) ;
546
-
547
- return listeners || [ ] ;
548
- }
549
-
550
450
unsubscribe ( ...args : unknown [ ] /* [event], listener */ ) : void {
551
451
const [ event , listener ] = RealtimeChannel . processListenerArgs ( args ) ;
552
452
553
453
// If we either have a filtered listener, a filter or both we need to do additional processing to find the original function(s)
554
454
if ( ( typeof event === 'object' && ! listener ) || this . filteredSubscriptions ?. has ( listener ) ) {
555
- this . _getAndDeleteFilteredSubscriptions ( event , listener ) . forEach ( ( l ) => this . subscriptions . off ( l ) ) ;
455
+ FilteredSubscriptions . getAndDeleteFilteredSubscriptions ( this , event , listener ) . forEach ( ( l ) =>
456
+ this . subscriptions . off ( l )
457
+ ) ;
556
458
return ;
557
459
}
558
460
0 commit comments