Created
March 1, 2023 17:52
-
-
Save 7474/499e5755393c376b1d48b5a986100d66 to your computer and use it in GitHub Desktop.
Apollo for Pusher
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ApolloLink, FetchResult, NextLink, Observable, Observer, Operation } from '@apollo/client' | |
import { Subscription } from 'zen-observable-ts' | |
class PusherObservable extends Observable<FetchResult> { | |
subscribeInternal: any | |
subscribe(observer: Observer<FetchResult>): Subscription | |
subscribe(onNext: (value: FetchResult) => void, onError?: (error: any) => void, onComplete?: () => void): Subscription | |
subscribe(observer: any) { | |
super.subscribe(observer) | |
if (typeof observer !== 'object' || observer === null) { | |
observer = { | |
next: observer, | |
error: arguments[1], | |
complete: arguments[2] | |
} | |
} | |
return this.subscribeInternal(observer) | |
} | |
} | |
// Inspired by https://github.com/rmosolgo/graphql-ruby/blob/master/javascript_client/src/subscriptions/PusherLink.ts | |
class PusherLink extends ApolloLink { | |
pusher: any | |
constructor(options: any) { | |
super() | |
this.pusher = options.pusher | |
} | |
request(operation: Operation, forward?: NextLink): Observable<FetchResult> | null { | |
const subscribeObservable = new PusherObservable((_observer) => { | |
// | |
}) | |
// Override subscribe to return an `unsubscribe` object, see | |
// https://github.com/apollographql/subscriptions-transport-ws/blob/master/src/client.ts#L182-L212 | |
const subscribe = (observer: Observer<FetchResult>) => { | |
let subscriptionChannel: any | |
if (forward) { | |
forward(operation).subscribe({ | |
next: (data) => { | |
// If the operation has the subscription channel, it's a subscription | |
subscriptionChannel = data?.extensions?.lighthouse_subscriptions.channel ?? null | |
// No subscription found in the response, pipe data through | |
if (!subscriptionChannel) { | |
observer.next?.(data) | |
observer.complete?.() | |
return | |
} | |
this.subscribeToChannel(subscriptionChannel, observer) | |
} | |
}) | |
} | |
// Return an object that will unsubscribe_if the query was a subscription | |
return { | |
closed: false, | |
unsubscribe: () => { | |
subscriptionChannel && this.unsubscribeFromChannel(subscriptionChannel) | |
} | |
} | |
} | |
subscribeObservable.subscribeInternal = subscribe | |
return subscribeObservable | |
} | |
subscribeToChannel(subscriptionChannel: any, observer: any) { | |
this.pusher.subscribe(subscriptionChannel).bind('lighthouse-subscription', (payload: any) => { | |
if (!payload.more) { | |
this.unsubscribeFromChannel(subscriptionChannel) | |
observer.complete() | |
} | |
const result = payload.result | |
if (result) { | |
observer.next(result) | |
} | |
}) | |
} | |
unsubscribeFromChannel(subscriptionChannel: any) { | |
this.pusher.unsubscribe(subscriptionChannel) | |
} | |
} | |
export default PusherLink |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment