import React , { useCallback } from "react" ; import { InferableComponentEnhancer } from "recompose" ; import { Disposable , Environment , GraphQLSubscriptionConfig , requestSubscription as requestSubscriptionRelay , } from "relay-runtime" ; import { CoralContext , useCoralContext } from "../bootstrap" ; import { resolveModule } from "./helpers" ; export type SubscriptionVariables < T extends { variables : any ; } > = T [ "variables" ] ; export interface Subscription < N , V > { name : N ; subscribe : ( environment : Environment , variables : V , context : CoralContext ) => Disposable ; } export type SubscriptionProp < T extends Subscription < any , any > > = T extends Subscription < any , infer V > ? Parameters < T [ "subscribe" ] > [ 1 ] extends undefined ? ( ) => Disposable : keyof Parameters < T [ "subscribe" ] > [ 1 ] extends never ? ( ) => Disposable : ( variables : V ) => Disposable : never ; export function createSubscription < N extends string , V > ( name , subscriptionConfig ) { return { name , subscribe : ( environment , variables , context ) => { context . eventEmitter . emit ( `subscription.${ name }.subscribe` , variables ) ; const config = subscriptionConfig ( environment , variables , context ) ; const disposable = requestSubscription ( environment , { ... config , onNext : ( ... args ) => { context . eventEmitter . emit ( `subscription.${ name }.data` , variables ) ; if ( config . onNext ) { config . onNext ( ... args ) ; } } , } ) ; return { dispose : ( ) => { context . eventEmitter . emit ( `subscription.${ name }.unsubscribe` , variables ) ; disposable . dispose ( ) ; } , } ; } , } ; } export function requestSubscription < TSubscriptionPayload > ( environment , config ) { return requestSubscriptionRelay ( environment , { ... config , subscription : resolveModule ( config . subscription ) , } ) ; } /**
 * useSubscription is a React Hook that
 * returns a callback to subscribes to a Subscription.
 */ export function useSubscription < V > ( subscription ) { const context = useCoralContext ( ) ; return useCallback < SubscriptionProp < typeof subscription > > ( ( ( variables ) => { context . eventEmitter . emit ( `subscription.${ subscription . name }` , variables ) ; return subscription . subscribe ( context . relayEnvironment , variables , context ) ; } ) as any , [ context , subscription ] ) ; } deprecated export function withSubscription < N extends string , V , R > ( subscription ) { return ( BaseComponent ) => { { const sub = useSubscription ( subscription ) ; return function WithSubscription ( props ) { const finalProps = { ... props , [ subscription . name ] : sub , } ; return < BaseComponent { ... finalProps } / > ; } as any ; } } ; } /**
 * Combines disposables into one.
 */ export function combineDisposables ( ... disposables ) { return { dispose : ( ) => { disposables . forEach ( ( d ) => d . dispose ( ) ) ; } , } ; }