Skip to content

Commit

Permalink
feat: Support NestJS filter function for subscriptions (#2977)
Browse files Browse the repository at this point in the history
  • Loading branch information
gthau authored Sep 5, 2023
1 parent 3ed9a1a commit bb583a1
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/fluffy-queens-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-yoga/nestjs': minor
---

Support for NestJS @Subscription.filter method in YogaDriver.
13 changes: 13 additions & 0 deletions packages/nestjs/__tests__/fixtures/graphql/cats/cats.resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,17 @@ export class CatsResolvers {
yield { greetings: hi };
}
}

@Subscription('filteredGreetings', {
filter: (payload, variables) => {
return payload.filteredGreetings
.toLowerCase()
.startsWith(variables.firstLetter.toLowerCase());
},
})
async *filteredGreetings() {
for (const hi of ['Hi', 'Bonjour', 'Hola', 'Ciao', 'Zdravo']) {
yield { filteredGreetings: hi };
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type Mutation {
type Subscription {
catCreated: Cat
greetings: String
filteredGreetings(firstLetter: String!): String
}

type Cat {
Expand Down
30 changes: 30 additions & 0 deletions packages/nestjs/__tests__/subscriptions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,33 @@ event: complete
"
`);
});

it("should execute Nest Subscription decorator's filter function on each emitted value", async () => {
const sub = await fetch(url, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
query: /* GraphQL */ `
subscription {
filteredGreetings(firstLetter: "H")
}
`,
}),
});

await expect(sub.text()).resolves.toMatchInlineSnapshot(`
":
event: next
data: {"data":{"filteredGreetings":"Hi"}}
event: next
data: {"data":{"filteredGreetings":"Hola"}}
event: complete
"
`);
});
24 changes: 23 additions & 1 deletion packages/nestjs/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Express, Request as ExpressRequest, Response as ExpressResponse } from 'express';
import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
import { printSchema } from 'graphql';
import { createYoga, YogaServerInstance, YogaServerOptions } from 'graphql-yoga';
import { createYoga, filter, pipe, YogaServerInstance, YogaServerOptions } from 'graphql-yoga';
import type { ExecutionParams } from 'subscriptions-transport-ws';
import { Injectable, Logger } from '@nestjs/common';
import {
Expand Down Expand Up @@ -143,6 +143,28 @@ export abstract class AbstractYogaDriver<
return reply;
});
}

public subscriptionWithFilter<TPayload, TVariables, TContext>(
instanceRef: unknown,
filterFn: (
payload: TPayload,
variables: TVariables,
context: TContext,
) => boolean | Promise<boolean>,
// disable next error, the original function in @nestjs/graphql is also untyped
// eslint-disable-next-line @typescript-eslint/ban-types
createSubscribeContext: Function,
) {
return async (...args: [TPayload, TVariables, TContext]) => {
return pipe(
await createSubscribeContext()(...args),
filter((payload: TPayload) =>
// typecast the spread sliced args to avoid error TS 2556, see https://github.com/microsoft/TypeScript/issues/49802
filterFn.call(instanceRef, payload, ...(args.slice(1) as [TVariables, TContext])),
),
);
};
}
}

@Injectable()
Expand Down

0 comments on commit bb583a1

Please sign in to comment.