@@ -4,6 +4,10 @@ import { arrayify, fill, isThenable, loadModule, logger } from '@sentry/utils';
4
4
5
5
import { shouldDisableAutoInstrumentation } from './utils/node-utils' ;
6
6
7
+ interface ApolloOptions {
8
+ useNestjs ?: boolean ;
9
+ }
10
+
7
11
type ApolloResolverGroup = {
8
12
[ key : string ] : ( ) => unknown ;
9
13
} ;
@@ -24,6 +28,19 @@ export class Apollo implements Integration {
24
28
*/
25
29
public name : string = Apollo . id ;
26
30
31
+ private readonly _useNest : boolean ;
32
+
33
+ /**
34
+ * @inheritDoc
35
+ */
36
+ public constructor (
37
+ options : ApolloOptions = {
38
+ useNestjs : false ,
39
+ } ,
40
+ ) {
41
+ this . _useNest = ! ! options . useNestjs ;
42
+ }
43
+
27
44
/**
28
45
* @inheritDoc
29
46
*/
@@ -33,62 +50,111 @@ export class Apollo implements Integration {
33
50
return ;
34
51
}
35
52
36
- const pkg = loadModule < {
37
- ApolloServerBase : {
38
- prototype : {
39
- constructSchema : ( ) => unknown ;
53
+ if ( this . _useNest ) {
54
+ const pkg = loadModule < {
55
+ GraphQLFactory : {
56
+ prototype : {
57
+ create : ( resolvers : ApolloModelResolvers [ ] ) => unknown ;
58
+ } ;
40
59
} ;
41
- } ;
42
- } > ( 'apollo-server-core' ) ;
60
+ } > ( '@nestjs/graphql' ) ;
43
61
44
- if ( ! pkg ) {
45
- __DEBUG_BUILD__ && logger . error ( 'Apollo Integration was unable to require apollo-server-core package.' ) ;
46
- return ;
47
- }
62
+ if ( ! pkg ) {
63
+ __DEBUG_BUILD__ && logger . error ( 'Apollo-NestJS Integration was unable to require @nestjs/graphql package.' ) ;
64
+ return ;
65
+ }
66
+
67
+ /**
68
+ * Iterate over resolvers of NestJS ResolversExplorerService before schemas are constructed.
69
+ */
70
+ fill (
71
+ pkg . GraphQLFactory . prototype ,
72
+ 'mergeWithSchema' ,
73
+ function ( orig : ( this : unknown , ...args : unknown [ ] ) => unknown ) {
74
+ return function (
75
+ this : { resolversExplorerService : { explore : ( ) => ApolloModelResolvers [ ] } } ,
76
+ ...args : unknown [ ]
77
+ ) {
78
+ fill ( this . resolversExplorerService , 'explore' , function ( orig : ( ) => ApolloModelResolvers [ ] ) {
79
+ return function ( this : unknown ) {
80
+ const resolvers = arrayify ( orig . call ( this ) ) ;
81
+
82
+ const instrumentedResolvers = instrumentResolvers ( resolvers , getCurrentHub ) ;
83
+
84
+ return instrumentedResolvers ;
85
+ } ;
86
+ } ) ;
87
+
88
+ return orig . call ( this , ...args ) ;
89
+ } ;
90
+ } ,
91
+ ) ;
92
+ } else {
93
+ const pkg = loadModule < {
94
+ ApolloServerBase : {
95
+ prototype : {
96
+ constructSchema : ( config : unknown ) => unknown ;
97
+ } ;
98
+ } ;
99
+ } > ( 'apollo-server-core' ) ;
100
+
101
+ if ( ! pkg ) {
102
+ __DEBUG_BUILD__ && logger . error ( 'Apollo Integration was unable to require apollo-server-core package.' ) ;
103
+ return ;
104
+ }
105
+
106
+ /**
107
+ * Iterate over resolvers of the ApolloServer instance before schemas are constructed.
108
+ */
109
+ fill ( pkg . ApolloServerBase . prototype , 'constructSchema' , function ( orig : ( config : unknown ) => unknown ) {
110
+ return function ( this : {
111
+ config : { resolvers ?: ApolloModelResolvers [ ] ; schema ?: unknown ; modules ?: unknown } ;
112
+ } ) {
113
+ if ( ! this . config . resolvers ) {
114
+ if ( __DEBUG_BUILD__ ) {
115
+ if ( this . config . schema ) {
116
+ logger . warn (
117
+ 'Apollo integration is not able to trace `ApolloServer` instances constructed via `schema` property.' +
118
+ 'If you are using NestJS with Apollo, please use `Sentry.Integrations.Apollo({ useNestjs: true })` instead.' ,
119
+ ) ;
120
+ logger . warn ( ) ;
121
+ } else if ( this . config . modules ) {
122
+ logger . warn (
123
+ 'Apollo integration is not able to trace `ApolloServer` instances constructed via `modules` property.' ,
124
+ ) ;
125
+ }
48
126
49
- /**
50
- * Iterate over resolvers of the ApolloServer instance before schemas are constructed.
51
- */
52
- fill ( pkg . ApolloServerBase . prototype , 'constructSchema' , function ( orig : ( ) => unknown ) {
53
- return function ( this : { config : { resolvers ?: ApolloModelResolvers [ ] ; schema ?: unknown ; modules ?: unknown } } ) {
54
- if ( ! this . config . resolvers ) {
55
- if ( __DEBUG_BUILD__ ) {
56
- if ( this . config . schema ) {
57
- logger . warn (
58
- 'Apollo integration is not able to trace `ApolloServer` instances constructed via `schema` property.' ,
59
- ) ;
60
- } else if ( this . config . modules ) {
61
- logger . warn (
62
- 'Apollo integration is not able to trace `ApolloServer` instances constructed via `modules` property.' ,
63
- ) ;
127
+ logger . error ( 'Skipping tracing as no resolvers found on the `ApolloServer` instance.' ) ;
64
128
}
65
129
66
- logger . error ( 'Skipping tracing as no resolvers found on the `ApolloServer` instance.' ) ;
130
+ return orig . call ( this ) ;
67
131
}
68
132
69
- return orig . call ( this ) ;
70
- }
133
+ const resolvers = arrayify ( this . config . resolvers ) ;
71
134
72
- const resolvers = arrayify ( this . config . resolvers ) ;
73
-
74
- this . config . resolvers = resolvers . map ( model => {
75
- Object . keys ( model ) . forEach ( resolverGroupName => {
76
- Object . keys ( model [ resolverGroupName ] ) . forEach ( resolverName => {
77
- if ( typeof model [ resolverGroupName ] [ resolverName ] !== 'function' ) {
78
- return ;
79
- }
135
+ this . config . resolvers = instrumentResolvers ( resolvers , getCurrentHub ) ;
80
136
81
- wrapResolver ( model , resolverGroupName , resolverName , getCurrentHub ) ;
82
- } ) ;
83
- } ) ;
137
+ return orig . call ( this ) ;
138
+ } ;
139
+ } ) ;
140
+ }
141
+ }
142
+ }
84
143
85
- return model ;
86
- } ) ;
144
+ function instrumentResolvers ( resolvers : ApolloModelResolvers [ ] , getCurrentHub : ( ) => Hub ) : ApolloModelResolvers [ ] {
145
+ return resolvers . map ( model => {
146
+ Object . keys ( model ) . forEach ( resolverGroupName => {
147
+ Object . keys ( model [ resolverGroupName ] ) . forEach ( resolverName => {
148
+ if ( typeof model [ resolverGroupName ] [ resolverName ] !== 'function' ) {
149
+ return ;
150
+ }
87
151
88
- return orig . call ( this ) ;
89
- } ;
152
+ wrapResolver ( model , resolverGroupName , resolverName , getCurrentHub ) ;
153
+ } ) ;
90
154
} ) ;
91
- }
155
+
156
+ return model ;
157
+ } ) ;
92
158
}
93
159
94
160
/**
0 commit comments