From b12f72096aad6f1b383b11335187428b211474fe Mon Sep 17 00:00:00 2001 From: Lee Byron Date: Wed, 26 May 2021 16:45:47 -0700 Subject: [PATCH] TS: Fix strict issues in src/subscription --- .../__tests__/mapAsyncIterator-test.ts | 12 +++++++++--- src/subscription/__tests__/simplePubSub.ts | 14 ++++++++++---- src/subscription/__tests__/subscribe-test.ts | 11 +++++++---- src/subscription/mapAsyncIterator.ts | 3 ++- src/subscription/subscribe.ts | 2 +- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/subscription/__tests__/mapAsyncIterator-test.ts b/src/subscription/__tests__/mapAsyncIterator-test.ts index e5e374e256..077ea04360 100644 --- a/src/subscription/__tests__/mapAsyncIterator-test.ts +++ b/src/subscription/__tests__/mapAsyncIterator-test.ts @@ -33,7 +33,9 @@ describe('mapAsyncIterator', () => { next(): Promise> { if (items.length > 0) { - return Promise.resolve({ done: false, value: items.shift() }); + const value = items[0]; + items.shift(); + return Promise.resolve({ done: false, value }); } return Promise.resolve({ done: true, value: undefined }); @@ -130,9 +132,11 @@ describe('mapAsyncIterator', () => { return this; }, next() { + const value = items[0]; + items.shift(); return Promise.resolve({ done: items.length === 0, - value: items.shift(), + value, }); }, }; @@ -194,9 +198,11 @@ describe('mapAsyncIterator', () => { return this; }, next() { + const value = items[0]; + items.shift(); return Promise.resolve({ done: items.length === 0, - value: items.shift(), + value, }); }, }; diff --git a/src/subscription/__tests__/simplePubSub.ts b/src/subscription/__tests__/simplePubSub.ts index e4d3c5569a..7efdf40e57 100644 --- a/src/subscription/__tests__/simplePubSub.ts +++ b/src/subscription/__tests__/simplePubSub.ts @@ -1,3 +1,5 @@ +import { invariant } from '../../jsutils/invariant'; + /** * Create an AsyncIterator from an EventEmitter. Useful for mocking a * PubSub system for tests. @@ -18,7 +20,7 @@ export class SimplePubSub { getSubscriber(transform: (value: T) => R): AsyncGenerator { const pullQueue: Array<(result: IteratorResult) => void> = []; - const pushQueue = []; + const pushQueue: Array = []; let listening = true; this._subscribers.add(pushValue); @@ -33,13 +35,15 @@ export class SimplePubSub { }; return { - next() { + next(): Promise> { if (!listening) { return Promise.resolve({ value: undefined, done: true }); } if (pushQueue.length > 0) { - return Promise.resolve({ value: pushQueue.shift(), done: false }); + const value = pushQueue[0]; + pushQueue.shift(); + return Promise.resolve({ value, done: false }); } return new Promise((resolve) => pullQueue.push(resolve)); }, @@ -59,7 +63,9 @@ export class SimplePubSub { function pushValue(event: T): void { const value: R = transform(event); if (pullQueue.length > 0) { - pullQueue.shift()({ value, done: false }); + const receiver = pullQueue.shift(); + invariant(receiver); + receiver({ value, done: false }); } else { pushQueue.push(value); } diff --git a/src/subscription/__tests__/subscribe-test.ts b/src/subscription/__tests__/subscribe-test.ts index 85a0a7e574..dcb02e042c 100644 --- a/src/subscription/__tests__/subscribe-test.ts +++ b/src/subscription/__tests__/subscribe-test.ts @@ -42,7 +42,8 @@ const InboxType = new GraphQLObjectType({ }, unread: { type: GraphQLInt, - resolve: (inbox) => inbox.emails.filter((email) => email.unread).length, + resolve: (inbox) => + inbox.emails.filter((email: any) => email.unread).length, }, emails: { type: new GraphQLList(EmailType) }, }, @@ -103,7 +104,7 @@ function createSubscription(pubsub: SimplePubSub) { }, ]; - const data = { + const data: any = { inbox: { emails }, // FIXME: we shouldn't use mapAsyncIterator here since it makes tests way more complex importantEmail: pubsub.getSubscriber((newEmail) => { @@ -122,7 +123,7 @@ function createSubscription(pubsub: SimplePubSub) { } async function expectPromise(promise: Promise) { - let caughtError; + let caughtError: Error; try { await promise; @@ -136,7 +137,7 @@ async function expectPromise(promise: Promise) { toReject() { expect(caughtError).to.be.an.instanceOf(Error); }, - toRejectWith(message) { + toRejectWith(message: string) { expect(caughtError).to.be.an.instanceOf(Error); expect(caughtError).to.have.property('message', message); }, @@ -312,6 +313,7 @@ describe('Subscription Initialization Phase', () => { }), }); + // TODO ts-expect-error (schema must not be null) (await expectPromise(subscribe({ schema: null, document }))).toRejectWith( 'Expected null to be a GraphQL schema.', ); @@ -321,6 +323,7 @@ describe('Subscription Initialization Phase', () => { 'Expected undefined to be a GraphQL schema.', ); + // TODO ts-expect-error (document must not be null) (await expectPromise(subscribe({ schema, document: null }))).toRejectWith( 'Must provide document.', ); diff --git a/src/subscription/mapAsyncIterator.ts b/src/subscription/mapAsyncIterator.ts index 4e9563c752..bc0d167857 100644 --- a/src/subscription/mapAsyncIterator.ts +++ b/src/subscription/mapAsyncIterator.ts @@ -39,9 +39,10 @@ export function mapAsyncIterator( return mapResult(await iterator.next()); }, async return(): Promise> { + // If iterator.return() does not exist, then type R must be undefined. return typeof iterator.return === 'function' ? mapResult(await iterator.return()) - : { value: undefined, done: true }; + : { value: undefined as any, done: true }; }, async throw(error?: unknown) { return typeof iterator.throw === 'function' diff --git a/src/subscription/subscribe.ts b/src/subscription/subscribe.ts index 4d194d894c..bb150ac750 100644 --- a/src/subscription/subscribe.ts +++ b/src/subscription/subscribe.ts @@ -92,7 +92,7 @@ export async function subscribe( // the GraphQL specification. The `execute` function provides the // "ExecuteSubscriptionEvent" algorithm, as it is nearly identical to the // "ExecuteQuery" algorithm, for which `execute` is also used. - const mapSourceToResponse = (payload) => + const mapSourceToResponse = (payload: unknown) => execute({ schema, document,