saihaj / graphql-ts-node-advanced-tutorial

WIP tutorial

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

graphql-subscriptions PubSub.prototype.asyncIterator is wrongly typed

n1ru4l opened this issue · comments

image

Instead of AsyncIterator it should return AsyncIterable .... (apollographql/graphql-subscriptions#232) This typing is incorrect for a long time and nobody bothers reviewing the PRs and fixing it...

This is causing TypeScript errors, I got when I set up the project.

image

Possible solutions

patch-package

Not great for a tutorial and also I would like to avoid any apollo "maintained" libraries.

Just use a simple PubSub inlined

This is all you need. I have been using it for a while with https://github.com/dungeon-revealer/dungeon-revealer/blob/master/server/pubsub.ts. It should be sufficient for the use-cases of the tutorial?

import { EventEmitter, on } from "events";

type PubSubPublishArgsByKey = {
  [key: string]: [any] | [number | string, any];
};

export const createChannelPubSub = <
  TPubSubPublishArgsByKey extends PubSubPublishArgsByKey
>() => {
  const emitter = new EventEmitter();

  return {
    publish: <TKey extends Extract<keyof TPubSubPublishArgsByKey, string>>(
      routingKey: TKey,
      ...args: TPubSubPublishArgsByKey[TKey]
    ) => {
      if (args[1] !== undefined) {
        emitter.emit(`${routingKey}:${args[0] as number}`, args[1]);
      }

      emitter.emit(routingKey, args[0]);
    },
    subscribe: async function* <
      TKey extends Extract<keyof TPubSubPublishArgsByKey, string>
    >(
      ...[routingKey, id]: TPubSubPublishArgsByKey[TKey][1] extends undefined
        ? [TKey]
        : [TKey, TPubSubPublishArgsByKey[TKey][0]]
    ): AsyncGenerator<
      TPubSubPublishArgsByKey[TKey][1] extends undefined
        ? TPubSubPublishArgsByKey[TKey][0]
        : TPubSubPublishArgsByKey[TKey][1]
    > {
      const asyncIterator = on(
        emitter,
        id === undefined ? routingKey : `${routingKey}:${id as number}`
      );
      for await (const [value] of asyncIterator) {
        yield value as any;
      }
    },
  };
};