import { genString } from "../gen-string" ; export type callback < T = any > = ( value : T ) => void ; export interface Subscription { unsubscribe : ( ) => void ; } export class Beacon < T > { subscribers : Record < string , callback < T > > = { } ; subscribe ( cb ) { const key = genString . ofLength ( 5 ) ; this . subscribers [ key ] = cb ; return { unsubscribe : ( ) => delete this . subscribers [ key ] } ; } next ( value ) { for ( const key in this . subscribers ) { this . subscribers [ key ] ( value ) ; } } first ( cb = ( ) => true ) { return first < T > ( this , cb ) ; } nthEvent ( n ) { return nthEvent ( this , n ) ; } } export class Bundle { subscriptions : Subscription [ ] = [ ] ; add ( subscription ) { this . subscriptions . push ( subscription ) ; } unsubscribe ( ) { this . subscriptions . forEach ( subscription => subscription . unsubscribe ( ) ) ; this . subscriptions = [ ] ; } } export const nthEvent = < T > ( beacon , n ) : Promise < T > => { return new Promise ( res => { let count = 0 ; const subscription = beacon . subscribe ( value => { count ++ ; if ( count === n ) { res ( value ) ; subscription . unsubscribe ( ) ; } } ) ; } ) ; } ; export const first = < T > ( beacon , cb = ( ) => true ) : Promise < T > => { return new Promise ( res => { const subscription = beacon . subscribe ( value => { const result = cb ( value ) ; if ( result === true ) { res ( value ) ; subscription . unsubscribe ( ) ; } } ) ; } ) ; } ;