@@ -156,6 +156,15 @@ export type OperationContext =
156156 | undefined
157157 | null ;
158158
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+
159168/** @category Server */
160169export type OperationArgs < Context extends OperationContext = undefined > =
161170 ExecutionArgs & { contextValue ?: Context } ;
@@ -313,6 +322,14 @@ export interface HandlerOptions<
313322 | ExecutionResult
314323 | Response
315324 | 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 ;
316333}
317334
318335/**
@@ -402,6 +419,7 @@ export function createHandler<
402419 rootValue,
403420 onSubscribe,
404421 onOperation,
422+ formatError = ( err ) => err ,
405423 } = options ;
406424
407425 return async function handler ( req ) {
@@ -525,7 +543,7 @@ export function createHandler<
525543 // request parameters are checked and now complete
526544 params = partParams as RequestParams ;
527545 } catch ( err ) {
528- return makeResponse ( err , acceptedMediaType ) ;
546+ return makeResponse ( err , acceptedMediaType , formatError ) ;
529547 }
530548
531549 let args : OperationArgs < Context > ;
@@ -535,7 +553,7 @@ export function createHandler<
535553 isExecutionResult ( maybeResErrsOrArgs ) ||
536554 areGraphQLErrors ( maybeResErrsOrArgs )
537555 )
538- return makeResponse ( maybeResErrsOrArgs , acceptedMediaType ) ;
556+ return makeResponse ( maybeResErrsOrArgs , acceptedMediaType , formatError ) ;
539557 else if ( maybeResErrsOrArgs ) args = maybeResErrsOrArgs ;
540558 else {
541559 if ( ! schema ) throw new Error ( 'The GraphQL schema is not provided' ) ;
@@ -546,7 +564,7 @@ export function createHandler<
546564 try {
547565 document = parse ( query ) ;
548566 } catch ( err ) {
549- return makeResponse ( err , acceptedMediaType ) ;
567+ return makeResponse ( err , acceptedMediaType , formatError ) ;
550568 }
551569
552570 const resOrContext =
@@ -582,7 +600,7 @@ export function createHandler<
582600 }
583601 const validationErrs = validate ( args . schema , args . document , rules ) ;
584602 if ( validationErrs . length ) {
585- return makeResponse ( validationErrs , acceptedMediaType ) ;
603+ return makeResponse ( validationErrs , acceptedMediaType , formatError ) ;
586604 }
587605 }
588606
@@ -595,13 +613,15 @@ export function createHandler<
595613 return makeResponse (
596614 new GraphQLError ( 'Unable to detect operation AST' ) ,
597615 acceptedMediaType ,
616+ formatError ,
598617 ) ;
599618 }
600619
601620 if ( operation === 'subscription' ) {
602621 return makeResponse (
603622 new GraphQLError ( 'Subscriptions are not supported' ) ,
604623 acceptedMediaType ,
624+ formatError ,
605625 ) ;
606626 }
607627
@@ -642,10 +662,11 @@ export function createHandler<
642662 return makeResponse (
643663 new GraphQLError ( 'Subscriptions are not supported' ) ,
644664 acceptedMediaType ,
665+ formatError ,
645666 ) ;
646667 }
647668
648- return makeResponse ( result , acceptedMediaType ) ;
669+ return makeResponse ( result , acceptedMediaType , formatError ) ;
649670 } ;
650671}
651672
@@ -720,14 +741,18 @@ export function makeResponse(
720741 | Readonly < GraphQLError >
721742 | Readonly < Error > ,
722743 acceptedMediaType : AcceptableMediaType ,
744+ formatError : FormatError ,
723745) : Response {
724746 if (
725747 resultOrErrors instanceof Error &&
726748 // because GraphQLError extends the Error class
727749 ! isGraphQLError ( resultOrErrors )
728750 ) {
729751 return [
730- JSON . stringify ( { errors : [ resultOrErrors ] } , jsonErrorReplacer ) ,
752+ JSON . stringify (
753+ { errors : [ formatError ( resultOrErrors ) ] } ,
754+ jsonErrorReplacer ,
755+ ) ,
731756 {
732757 status : 400 ,
733758 statusText : 'Bad Request' ,
@@ -744,7 +769,7 @@ export function makeResponse(
744769 : null ;
745770 if ( errors ) {
746771 return [
747- JSON . stringify ( { errors } , jsonErrorReplacer ) ,
772+ JSON . stringify ( { errors : errors . map ( formatError ) } , jsonErrorReplacer ) ,
748773 {
749774 ...( acceptedMediaType === 'application/json'
750775 ? {
@@ -766,7 +791,15 @@ export function makeResponse(
766791 }
767792
768793 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+ ) ,
770803 {
771804 status : 200 ,
772805 statusText : 'OK' ,
0 commit comments