Skip to content

Subscriptions

Davide Gheri edited this page Feb 19, 2021 · 3 revisions

Mercurius supports subscriptions out of the box

The PubSub instance is exposed via the GraphQL Context, accessible with the @nestjs/graphql @Context decorator.

The signature of Mercurius pubSub.subscribe() is not compatible with the expected from @nestjs/graphql (it expect an AsyncIterator). nestjs-mercurius offers a toAsyncIterator function to handle this case.

import { PubSub } from 'mercurius';
import { toAsyncIterator } from 'nestjs-mercurius';
//...
@Mutation(() => Cat)
async createCat(
  @Args() data: CreateCatArgs,
  @Context('pubsub'): pubSub: PubSub,
) {
  const cat = await this.catService.create(data);
  pubSub.publish({
    topic: 'CatCreated',
    payload: { cat },
  });
  

  return cat;
}

@Subscription(() => Cat, {
  resolve: payload => payload.cat,
  filter: (payload, variables) => payload.name === variables.name, 
})
onCatCreated(
  @Args('name') name: string,
  @Context('pubsub') pubSub: PubSub,
) {
  return toAsyncIterator(pubSub.subscribe('CatCreated'));
}

Sometimes you may wish to access the PubSub in other part of your applications, outside the resolver method context (ex. in a service, or in a controller), nestjs-mercurius globally expose a PubSubHost injectable to get the current PubSub instance:

import { PubSubHost } from 'nestjs-mercurius';

@Injectable()
export class CatService {
  constructor(
    private readonly pubSubHost: PubSubHost,
  ) {}

  createCat(data: CreateCatArgs) {
    const cat = new Cat(data);
    
    const pubSub = this.pubSubHost.getInstance();
    pubSub?.publish({
      topic: 'CatCreated',
      payload: { cat },
    });

    return cat;
  }
}