@@ -156,6 +156,15 @@ export type OperationContext =
156
156
| undefined
157
157
| null ;
158
158
159
+ /**
160
+ * The (GraphQL) error formatter function.
161
+ *
162
+ * @category Server
163
+ */
164
+ export type FormatError = (
165
+ err : Readonly < GraphQLError | Error > ,
166
+ ) => GraphQLError | Error ;
167
+
159
168
/** @category Server */
160
169
export type OperationArgs < Context extends OperationContext = undefined > =
161
170
ExecutionArgs & { contextValue ?: Context } ;
@@ -313,6 +322,14 @@ export interface HandlerOptions<
313
322
| ExecutionResult
314
323
| Response
315
324
| void ;
325
+ /**
326
+ * Format handled errors to your satisfaction. Either GraphQL errors
327
+ * or safe request processing errors are meant by "handleded errors".
328
+ *
329
+ * If multiple errors have occured, all of them will be mapped using
330
+ * this formatter.
331
+ */
332
+ formatError ?: FormatError ;
316
333
}
317
334
318
335
/**
@@ -402,6 +419,7 @@ export function createHandler<
402
419
rootValue,
403
420
onSubscribe,
404
421
onOperation,
422
+ formatError = ( err ) => err ,
405
423
} = options ;
406
424
407
425
return async function handler ( req ) {
@@ -525,7 +543,7 @@ export function createHandler<
525
543
// request parameters are checked and now complete
526
544
params = partParams as RequestParams ;
527
545
} catch ( err ) {
528
- return makeResponse ( err , acceptedMediaType ) ;
546
+ return makeResponse ( err , acceptedMediaType , formatError ) ;
529
547
}
530
548
531
549
let args : OperationArgs < Context > ;
@@ -535,7 +553,7 @@ export function createHandler<
535
553
isExecutionResult ( maybeResErrsOrArgs ) ||
536
554
areGraphQLErrors ( maybeResErrsOrArgs )
537
555
)
538
- return makeResponse ( maybeResErrsOrArgs , acceptedMediaType ) ;
556
+ return makeResponse ( maybeResErrsOrArgs , acceptedMediaType , formatError ) ;
539
557
else if ( maybeResErrsOrArgs ) args = maybeResErrsOrArgs ;
540
558
else {
541
559
if ( ! schema ) throw new Error ( 'The GraphQL schema is not provided' ) ;
@@ -546,7 +564,7 @@ export function createHandler<
546
564
try {
547
565
document = parse ( query ) ;
548
566
} catch ( err ) {
549
- return makeResponse ( err , acceptedMediaType ) ;
567
+ return makeResponse ( err , acceptedMediaType , formatError ) ;
550
568
}
551
569
552
570
const resOrContext =
@@ -582,7 +600,7 @@ export function createHandler<
582
600
}
583
601
const validationErrs = validate ( args . schema , args . document , rules ) ;
584
602
if ( validationErrs . length ) {
585
- return makeResponse ( validationErrs , acceptedMediaType ) ;
603
+ return makeResponse ( validationErrs , acceptedMediaType , formatError ) ;
586
604
}
587
605
}
588
606
@@ -595,13 +613,15 @@ export function createHandler<
595
613
return makeResponse (
596
614
new GraphQLError ( 'Unable to detect operation AST' ) ,
597
615
acceptedMediaType ,
616
+ formatError ,
598
617
) ;
599
618
}
600
619
601
620
if ( operation === 'subscription' ) {
602
621
return makeResponse (
603
622
new GraphQLError ( 'Subscriptions are not supported' ) ,
604
623
acceptedMediaType ,
624
+ formatError ,
605
625
) ;
606
626
}
607
627
@@ -642,10 +662,11 @@ export function createHandler<
642
662
return makeResponse (
643
663
new GraphQLError ( 'Subscriptions are not supported' ) ,
644
664
acceptedMediaType ,
665
+ formatError ,
645
666
) ;
646
667
}
647
668
648
- return makeResponse ( result , acceptedMediaType ) ;
669
+ return makeResponse ( result , acceptedMediaType , formatError ) ;
649
670
} ;
650
671
}
651
672
@@ -720,14 +741,18 @@ export function makeResponse(
720
741
| Readonly < GraphQLError >
721
742
| Readonly < Error > ,
722
743
acceptedMediaType : AcceptableMediaType ,
744
+ formatError : FormatError ,
723
745
) : Response {
724
746
if (
725
747
resultOrErrors instanceof Error &&
726
748
// because GraphQLError extends the Error class
727
749
! isGraphQLError ( resultOrErrors )
728
750
) {
729
751
return [
730
- JSON . stringify ( { errors : [ resultOrErrors ] } , jsonErrorReplacer ) ,
752
+ JSON . stringify (
753
+ { errors : [ formatError ( resultOrErrors ) ] } ,
754
+ jsonErrorReplacer ,
755
+ ) ,
731
756
{
732
757
status : 400 ,
733
758
statusText : 'Bad Request' ,
@@ -744,7 +769,7 @@ export function makeResponse(
744
769
: null ;
745
770
if ( errors ) {
746
771
return [
747
- JSON . stringify ( { errors } , jsonErrorReplacer ) ,
772
+ JSON . stringify ( { errors : errors . map ( formatError ) } , jsonErrorReplacer ) ,
748
773
{
749
774
...( acceptedMediaType === 'application/json'
750
775
? {
@@ -766,7 +791,15 @@ export function makeResponse(
766
791
}
767
792
768
793
return [
769
- JSON . stringify ( resultOrErrors , jsonErrorReplacer ) ,
794
+ JSON . stringify (
795
+ 'errors' in resultOrErrors && resultOrErrors . errors
796
+ ? {
797
+ ...resultOrErrors ,
798
+ errors : resultOrErrors . errors . map ( formatError ) ,
799
+ }
800
+ : resultOrErrors ,
801
+ jsonErrorReplacer ,
802
+ ) ,
770
803
{
771
804
status : 200 ,
772
805
statusText : 'OK' ,
0 commit comments