1
1
import { DiscoveryService } from '@golevelup/nestjs-discovery' ;
2
- import { YogaDriver , YogaDriverConfig } from '@graphql-yoga/nestjs' ;
3
2
import { Injectable } from '@nestjs/common' ;
4
- import { HttpAdapter } from '../http' ;
3
+ import {
4
+ AbstractGraphQLDriver as AbstractDriver ,
5
+ GqlModuleOptions ,
6
+ } from '@nestjs/graphql' ;
7
+ import type { RouteOptions as FastifyRoute } from 'fastify' ;
8
+ import {
9
+ createYoga ,
10
+ YogaServerInstance ,
11
+ YogaServerOptions ,
12
+ } from 'graphql-yoga' ;
13
+ import { GqlContextType } from '~/common' ;
14
+ import { HttpAdapter , IRequest } from '../http' ;
15
+ import { IResponse } from '../http/types' ;
5
16
import { Plugin } from './plugin.decorator' ;
6
17
18
+ export interface ServerContext {
19
+ /** Cannot be `request` as {@link import('graphql-yoga').YogaInitialContext.request} overrides it */
20
+ req : IRequest ;
21
+ response : IResponse ;
22
+ }
23
+
24
+ export type DriverConfig = GqlModuleOptions &
25
+ Omit < YogaServerOptions < ServerContext , GqlContextType > , 'context' | 'schema' > ;
26
+
7
27
@Injectable ( )
8
- export class Driver extends YogaDriver < 'fastify' > {
28
+ export class Driver extends AbstractDriver < DriverConfig > {
29
+ private yoga : YogaServerInstance < ServerContext , { } > ;
30
+
9
31
constructor (
10
32
private readonly discovery : DiscoveryService ,
11
33
private readonly http : HttpAdapter ,
12
34
) {
13
35
super ( ) ;
14
36
}
15
37
16
- async start ( options : YogaDriverConfig < 'fastify' > ) {
38
+ async start ( options : DriverConfig ) {
39
+ const fastify = this . http . getInstance ( ) ;
40
+
17
41
// Do our plugin discovery / registration
18
42
const discoveredPlugins = await this . discovery . providersWithMetaAtKey (
19
43
Plugin . KEY ,
@@ -23,12 +47,36 @@ export class Driver extends YogaDriver<'fastify'> {
23
47
...new Set ( discoveredPlugins . map ( ( cls ) => cls . discoveredClass . instance ) ) ,
24
48
] ;
25
49
26
- await super . start ( options ) ;
50
+ this . yoga = createYoga ( {
51
+ ...options ,
52
+ graphqlEndpoint : options . path ,
53
+ logging : false ,
54
+ } ) ;
55
+
56
+ fastify . route ( {
57
+ method : [ 'GET' , 'POST' , 'OPTIONS' ] ,
58
+ url : this . yoga . graphqlEndpoint ,
59
+ handler : this . httpHandler ,
60
+ } ) ;
27
61
28
62
// Setup file upload handling
29
- const fastify = this . http . getInstance ( ) ;
30
63
fastify . addContentTypeParser ( 'multipart/form-data' , ( req , payload , done ) =>
31
64
done ( null ) ,
32
65
) ;
33
66
}
67
+
68
+ httpHandler : FastifyRoute [ 'handler' ] = async ( req , reply ) => {
69
+ const res = await this . yoga . handleNodeRequestAndResponse ( req , reply , {
70
+ req,
71
+ response : reply ,
72
+ } ) ;
73
+ return await reply
74
+ . headers ( Object . fromEntries ( res . headers ) )
75
+ . status ( res . status )
76
+ . send ( res . body ) ;
77
+ } ;
78
+
79
+ async stop ( ) {
80
+ // noop
81
+ }
34
82
}
0 commit comments