export type EventToAsyncUnHandler = ( ) => unknown ; type Resolve < T > = ( v : T ) => void ; type Reject = ( e : Error ) => void ; type Deferred < T > = { resolve : Resolve < T > ; reject : Reject ; promise : Promise < T > ; } ; function createDeferred < T = void > ( ) { let resolve ; let reject ; const promise = new Promise < T > ( ( ... args ) => ( [ resolve , reject ] = args ) ) ; return Object . freeze ( < Deferred < T > > { resolve : resolve ! , reject : reject ! , promise } ) ; } export type EventToAsyncOnOptions = { signal ? : AbortSignal ; } ; export function on < R extends [ ... any ] > ( onHandler , options ? ) { const comEvents = [ ] ; const unconsumedDeferred = [ ] ; const unHandle = onHandler ( ( ... args ) => { const deferred = unconsumedDeferred . shift ( ) ; if ( deferred ) { deferred . resolve ( { value : args , done : false } ) ; } else { comEvents . push ( args ) ; } } ) ; const abortSignal = options ?. signal ; let finished = false ; let error = null ; const offListener = ( ) => { unHandle ?. ( ) ; } ; const onAbort = ( ) => { abortSignal ?. removeEventListener ( "abort" , offListener ) ; error = new Error ( "Abort Error" ) ; } ; abortSignal ?. addEventListener ( "abort" , onAbort , { once : true } ) ; return { async next ( ) { const lastEvent = comEvents . shift ( ) ; if ( lastEvent ) { return { value : lastEvent , done : false } ; } if ( finished ) { return { value : undefined , done : true } ; } if ( error ) { return Promise . reject ( error ) ; } const deferred = createDeferred < IteratorResult < any > > ( ) ; unconsumedDeferred . push ( deferred ) ; return deferred . promise ; } , async return ( ) { finished = true ; offListener ( ) ; for ( const deferred of unconsumedDeferred ) { deferred . resolve ( { value : undefined , done : true } ) ; } return { value : undefined , done : true } ; } , async throw ( thrownError ) { error = thrownError ; offListener ( ) ; return { value : undefined , done : true } ; } , [ Symbol . asyncIterator ] ( ) { return this ; } } ; } export type EventToAsyncOnceOptions = { signal ? : AbortSignal ; } ; export function once < R extends [ ... any ] > ( onHandler , options ? ) { const unconsumedDeferred = createDeferred < R > ( ) ; const unEvent = onHandler ( ( ... args ) => { unconsumedDeferred . resolve ( args as R ) ; } ) ; const offListener = ( ) => { unEvent ?. ( ) ; } ; const onAbort = ( ) => { options ?. signal ?. removeEventListener ( "abort" , offListener ) ; unconsumedDeferred . reject ( new Error ( "Abort Error" ) ) ; } ; options ?. signal ?. addEventListener ( "abort" , onAbort , { once : true } ) ; return unconsumedDeferred . promise . finally ( ( ) => { offListener ( ) ; } ) ; }