@@ -26,10 +26,14 @@ import {
26
26
} from 'graphql' ;
27
27
28
28
import { parseBody } from './parseBody' ;
29
- import { renderGraphiQL , type GraphiQLOptions } from './renderGraphiQL' ;
29
+ import {
30
+ renderGraphiQL ,
31
+ type GraphiQLOptions ,
32
+ type GraphiQLData ,
33
+ } from './renderGraphiQL' ;
30
34
31
35
type $Request = IncomingMessage ;
32
- type $Response = ServerResponse & { | json ?: ? ( data : mixed ) => void | } ;
36
+ type $Response = ServerResponse & { | json ?: ( data : mixed ) => void | } ;
33
37
34
38
/**
35
39
* Used to configure the graphqlHTTP middleware by providing a schema
@@ -56,29 +60,29 @@ export type OptionsData = {|
56
60
/**
57
61
* A value to pass as the context to this middleware.
58
62
*/
59
- context ?: ? mixed ,
63
+ context ?: mixed ,
60
64
61
65
/**
62
66
* An object to pass as the rootValue to the graphql() function.
63
67
*/
64
- rootValue ?: ? mixed ,
68
+ rootValue ?: mixed ,
65
69
66
70
/**
67
71
* A boolean to configure whether the output should be pretty-printed.
68
72
*/
69
- pretty ?: ? boolean ,
73
+ pretty ?: boolean ,
70
74
71
75
/**
72
76
* An optional array of validation rules that will be applied on the document
73
77
* in additional to those defined by the GraphQL spec.
74
78
*/
75
- validationRules ?: ? $ReadOnlyArray < ( ValidationContext ) => ASTVisitor > ,
79
+ validationRules ?: $ReadOnlyArray < ( ValidationContext ) => ASTVisitor > ,
76
80
77
81
/**
78
82
* An optional function which will be used to validate instead of default `validate`
79
83
* from `graphql-js`.
80
84
*/
81
- customValidateFn ?: ? (
85
+ customValidateFn ?: (
82
86
schema : GraphQLSchema ,
83
87
documentAST : DocumentNode ,
84
88
rules : $ReadOnlyArray < ValidationRule > ,
@@ -88,7 +92,7 @@ export type OptionsData = {|
88
92
* An optional function which will be used to execute instead of default `execute`
89
93
* from `graphql-js`.
90
94
*/
91
- customExecuteFn ?: ? (
95
+ customExecuteFn ?: (
92
96
args : ExecutionArgs ,
93
97
) => ExecutionResult | Promise < ExecutionResult> ,
94
98
@@ -97,19 +101,19 @@ export type OptionsData = {|
97
101
* fulfilling a GraphQL operation. If no function is provided, GraphQL's
98
102
* default spec-compliant `formatError` function will be used.
99
103
*/
100
- customFormatErrorFn ?: ? ( error : GraphQLError ) => mixed ,
104
+ customFormatErrorFn ?: ( error : GraphQLError ) => mixed ,
101
105
102
106
/**
103
107
* An optional function which will be used to create a document instead of
104
108
* the default `parse` from `graphql-js`.
105
109
*/
106
- customParseFn ?: ? ( source : Source ) => DocumentNode ,
110
+ customParseFn ?: ( source : Source ) => DocumentNode ,
107
111
108
112
/**
109
113
* `formatError` is deprecated and replaced by `customFormatErrorFn`. It will
110
114
* be removed in version 1.0.0.
111
115
*/
112
- formatError ?: ? ( error : GraphQLError ) => mixed ,
116
+ formatError ?: ( error : GraphQLError ) => mixed ,
113
117
114
118
/**
115
119
* An optional function for adding additional metadata to the GraphQL response
@@ -121,27 +125,27 @@ export type OptionsData = {|
121
125
*
122
126
* This function may be async.
123
127
*/
124
- extensions ?: ? ( info : RequestInfo ) => { [ key : string ] : mixed , ... } ,
128
+ extensions ?: ( info : RequestInfo ) => { [ key : string ] : mixed , ... } ,
125
129
126
130
/**
127
131
* A boolean to optionally enable GraphiQL mode.
128
132
* Alternatively, instead of `true` you can pass in an options object.
129
133
*/
130
- graphiql ?: ? boolean | ? GraphiQLOptions ,
134
+ graphiql ?: boolean | GraphiQLOptions ,
131
135
132
136
/**
133
137
* A resolver function to use when one is not provided by the schema.
134
138
* If not provided, the default field resolver is used (which looks for a
135
139
* value or method on the source value with the field's name).
136
140
*/
137
- fieldResolver ?: ? GraphQLFieldResolver < mixed , mixed> ,
141
+ fieldResolver ?: GraphQLFieldResolver < mixed , mixed> ,
138
142
139
143
/**
140
144
* A type resolver function to use when none is provided by the schema.
141
145
* If not provided, the default type resolver is used (which looks for a
142
146
* `__typename` field or alternatively calls the `isTypeOf` method).
143
147
*/
144
- typeResolver ?: ? GraphQLTypeResolver < mixed , mixed> ,
148
+ typeResolver ?: GraphQLTypeResolver < mixed , mixed> ,
145
149
| } ;
146
150
147
151
/**
@@ -151,27 +155,27 @@ export type RequestInfo = {|
151
155
/**
152
156
* The parsed GraphQL document.
153
157
*/
154
- document : ? DocumentNode ,
158
+ document : DocumentNode ,
155
159
156
160
/**
157
161
* The variable values used at runtime.
158
162
*/
159
- variables : ? { + [ name : string ] : mixed , ... } ,
163
+ variables : { + [ name : string ] : mixed , ... } | null ,
160
164
161
165
/**
162
166
* The (optional) operation name requested.
163
167
*/
164
- operationName : ? string ,
168
+ operationName : string | null ,
165
169
166
170
/**
167
171
* The result of executing the operation.
168
172
*/
169
- result : ? ExecutionResult ,
173
+ result : ExecutionResult | null ,
170
174
171
175
/**
172
176
* A value to pass as the context to the graphql() function.
173
177
*/
174
- context ?: ? mixed ,
178
+ context ? : mixed ,
175
179
| } ;
176
180
177
181
type Middleware = ( request : $Request , response : $Response ) => Promise < void > ;
@@ -190,27 +194,32 @@ function graphqlHTTP(options: Options): Middleware {
190
194
request : $Request ,
191
195
response : $Response ,
192
196
) {
193
- // Higher scoped variables are referred to at various stages in the
194
- // asynchronous state machine below.
195
- let params ;
197
+ // Higher scoped variables are referred to at various stages in the asynchronous state machine below.
198
+ let params : GraphQLParams ;
196
199
let showGraphiQL = false ;
197
200
let graphiqlOptions ;
201
+ let formatErrorFn = formatError ;
202
+ let pretty = false ;
198
203
let result : ExecutionResult ;
199
- let optionsData ;
200
204
201
205
try {
202
206
// Parse the Request to get GraphQL request parameters.
203
207
try {
204
- params = await getGraphQLParams ( request ) ;
208
+ params = ( await getGraphQLParams ( request ) : GraphQLParams ) ;
205
209
} catch ( error ) {
206
210
// When we failed to parse the GraphQL parameters, we still need to get
207
211
// the options object, so make an options call to resolve just that.
208
- optionsData = await resolveOptions ( ) ;
212
+ const optionsData = await resolveOptions ( ) ;
213
+ pretty = optionsData . pretty ?? false ;
214
+ formatErrorFn =
215
+ optionsData . customFormatErrorFn ??
216
+ optionsData . formatError ??
217
+ formatErrorFn ;
209
218
throw error ;
210
219
}
211
220
212
221
// Then, resolve the Options to get OptionsData.
213
- optionsData = await resolveOptions ( params ) ;
222
+ const optionsData : OptionsData = await resolveOptions ( params ) ;
214
223
215
224
// Collect information from the options data object.
216
225
const schema = optionsData . schema ;
@@ -225,6 +234,12 @@ function graphqlHTTP(options: Options): Middleware {
225
234
const executeFn = optionsData . customExecuteFn ?? execute ;
226
235
const validateFn = optionsData . customValidateFn ?? validate ;
227
236
237
+ pretty = optionsData . pretty ?? false ;
238
+ formatErrorFn =
239
+ optionsData . customFormatErrorFn ??
240
+ optionsData . formatError ??
241
+ formatErrorFn ;
242
+
228
243
// Assert that schema is required.
229
244
if ( schema == null ) {
230
245
throw httpError (
@@ -354,7 +369,7 @@ function graphqlHTTP(options: Options): Middleware {
354
369
}
355
370
}
356
371
357
- result = { errors : error . graphqlErrors ?? [ error ] } ;
372
+ result = { data : undefined , errors : error . graphqlErrors ?? [ error ] } ;
358
373
}
359
374
360
375
// If no data was included in the result, that indicates a runtime query
@@ -368,10 +383,6 @@ function graphqlHTTP(options: Options): Middleware {
368
383
369
384
// Format any encountered errors.
370
385
if ( result . errors ) {
371
- const formatErrorFn =
372
- optionsData ?. customFormatErrorFn ??
373
- optionsData ?. formatError ??
374
- formatError ;
375
386
( result : any ) . errors = result . errors . map ( formatErrorFn ) ;
376
387
}
377
388
@@ -383,7 +394,6 @@ function graphqlHTTP(options: Options): Middleware {
383
394
// If "pretty" JSON isn't requested, and the server provides a
384
395
// response.json method (express), use that directly.
385
396
// Otherwise use the simplified sendResponse method.
386
- const pretty = optionsData ?. pretty || false ;
387
397
if ( ! pretty && typeof response . json === 'function' ) {
388
398
response . json ( result ) ;
389
399
} else {
@@ -394,9 +404,11 @@ function graphqlHTTP(options: Options): Middleware {
394
404
async function resolveOptions (
395
405
requestParams ?: GraphQLParams ,
396
406
) : Promise < OptionsData > {
397
- const optionsResult = await ( typeof options === 'function'
398
- ? options ( request , response , requestParams )
399
- : options ) ;
407
+ const optionsResult = await Promise . resolve (
408
+ typeof options === 'function'
409
+ ? options ( request , response , requestParams )
410
+ : options ,
411
+ ) ;
400
412
401
413
// Assert that optionsData is in fact an Object.
402
414
if ( optionsResult == null || typeof optionsResult !== 'object' ) {
@@ -419,17 +431,17 @@ function graphqlHTTP(options: Options): Middleware {
419
431
420
432
function respondWithGraphiQL (
421
433
response : $Response ,
422
- options : ? GraphiQLOptions ,
434
+ options ? : GraphiQLOptions ,
423
435
params ? : GraphQLParams ,
424
436
result ? : ExecutionResult ,
425
437
) : void {
426
- const payload = renderGraphiQL ( {
438
+ const data : GraphiQLData = {
427
439
query : params ?. query ,
428
440
variables : params ?. variables ,
429
441
operationName : params ?. operationName ,
430
442
result ,
431
- options ,
432
- } ) ;
443
+ } ;
444
+ const payload = renderGraphiQL ( data , options ) ;
433
445
return sendResponse ( response , 'text/html' , payload ) ;
434
446
}
435
447
0 commit comments