@@ -28,6 +28,8 @@ import type {
2828 QueryDefinition ,
2929 ResultDescription ,
3030 ResultTypeFrom ,
31+ SchemaFailureHandler ,
32+ SchemaFailureInfo ,
3133} from '../endpointDefinitions'
3234import {
3335 calculateProvidedBy ,
@@ -65,6 +67,7 @@ import {
6567 isRejectedWithValue ,
6668 SHOULD_AUTOBATCH ,
6769} from './rtkImports'
70+ import { parseWithSchema , NamedSchemaError } from '../standardSchema'
6871
6972export type BuildThunksApiEndpointQuery <
7073 Definition extends QueryDefinition < any , any , any , any , any > ,
@@ -329,6 +332,8 @@ export function buildThunks<
329332 api,
330333 assertTagType,
331334 selectors,
335+ onSchemaFailure,
336+ skipSchemaValidation : globalSkipSchemaValidation ,
332337} : {
333338 baseQuery : BaseQuery
334339 reducerPath : ReducerPath
@@ -337,6 +342,8 @@ export function buildThunks<
337342 api : Api < BaseQuery , Definitions , ReducerPath , any >
338343 assertTagType : AssertTagTypes
339344 selectors : AllSelectors
345+ onSchemaFailure : SchemaFailureHandler | undefined
346+ skipSchemaValidation : boolean | undefined
340347} ) {
341348 type State = RootState < any , string , ReducerPath >
342349
@@ -491,10 +498,14 @@ export function buildThunks<
491498 } ,
492499 ) => {
493500 const endpointDefinition = endpointDefinitions [ arg . endpointName ]
501+ const { metaSchema, skipSchemaValidation = globalSkipSchemaValidation } =
502+ endpointDefinition
494503
495504 try {
496- let transformResponse : TransformCallback =
497- getTransformCallbackForEndpoint ( endpointDefinition , 'transformResponse' )
505+ let transformResponse = getTransformCallbackForEndpoint (
506+ endpointDefinition ,
507+ 'transformResponse' ,
508+ )
498509
499510 const baseQueryApi = {
500511 signal,
@@ -551,7 +562,16 @@ export function buildThunks<
551562 finalQueryArg : unknown ,
552563 ) : Promise < QueryReturnValue > {
553564 let result : QueryReturnValue
554- const { extraOptions } = endpointDefinition
565+ const { extraOptions, argSchema, rawResponseSchema, responseSchema } =
566+ endpointDefinition
567+
568+ if ( argSchema && ! skipSchemaValidation ) {
569+ finalQueryArg = await parseWithSchema (
570+ argSchema ,
571+ finalQueryArg ,
572+ 'argSchema' ,
573+ )
574+ }
555575
556576 if ( forceQueryFn ) {
557577 // upsertQueryData relies on this to pass in the user-provided value
@@ -606,13 +626,34 @@ export function buildThunks<
606626
607627 if ( result . error ) throw new HandledError ( result . error , result . meta )
608628
609- const transformedResponse = await transformResponse (
610- result . data ,
629+ let { data } = result
630+
631+ if ( rawResponseSchema && ! skipSchemaValidation ) {
632+ data = await parseWithSchema (
633+ rawResponseSchema ,
634+ result . data ,
635+ 'rawResponseSchema' ,
636+ )
637+ }
638+
639+ let transformedResponse = await transformResponse (
640+ data ,
611641 result . meta ,
612642 finalQueryArg ,
613643 )
614644
615- return { ...result , data : transformedResponse }
645+ if ( responseSchema && ! skipSchemaValidation ) {
646+ transformedResponse = await parseWithSchema (
647+ responseSchema ,
648+ transformedResponse ,
649+ 'responseSchema' ,
650+ )
651+ }
652+
653+ return {
654+ ...result ,
655+ data : transformedResponse ,
656+ }
616657 }
617658
618659 if (
@@ -698,6 +739,14 @@ export function buildThunks<
698739 finalQueryReturnValue = await executeRequest ( arg . originalArgs )
699740 }
700741
742+ if ( metaSchema && ! skipSchemaValidation && finalQueryReturnValue . meta ) {
743+ finalQueryReturnValue . meta = await parseWithSchema (
744+ metaSchema ,
745+ finalQueryReturnValue . meta ,
746+ 'metaSchema' ,
747+ )
748+ }
749+
701750 // console.log('Final result: ', transformedData)
702751 return fulfillWithValue (
703752 finalQueryReturnValue . data ,
@@ -707,40 +756,78 @@ export function buildThunks<
707756 } ) ,
708757 )
709758 } catch ( error ) {
710- let catchedError = error
711- if ( catchedError instanceof HandledError ) {
712- let transformErrorResponse : TransformCallback =
713- getTransformCallbackForEndpoint (
759+ try {
760+ let caughtError = error
761+ if ( caughtError instanceof HandledError ) {
762+ let transformErrorResponse = getTransformCallbackForEndpoint (
714763 endpointDefinition ,
715764 'transformErrorResponse' ,
716765 )
766+ const { rawErrorResponseSchema, errorResponseSchema } =
767+ endpointDefinition
768+
769+ let { value, meta } = caughtError
770+
771+ if ( rawErrorResponseSchema && ! skipSchemaValidation ) {
772+ value = await parseWithSchema (
773+ rawErrorResponseSchema ,
774+ value ,
775+ 'rawErrorResponseSchema' ,
776+ )
777+ }
778+
779+ if ( metaSchema && ! skipSchemaValidation ) {
780+ meta = await parseWithSchema ( metaSchema , meta , 'metaSchema' )
781+ }
717782
718- try {
719- return rejectWithValue (
720- await transformErrorResponse (
721- catchedError . value ,
722- catchedError . meta ,
783+ try {
784+ let transformedErrorResponse = await transformErrorResponse (
785+ value ,
786+ meta ,
723787 arg . originalArgs ,
724- ) ,
725- addShouldAutoBatch ( { baseQueryMeta : catchedError . meta } ) ,
726- )
727- } catch ( e ) {
728- catchedError = e
788+ )
789+ if ( errorResponseSchema && ! skipSchemaValidation ) {
790+ transformedErrorResponse = await parseWithSchema (
791+ errorResponseSchema ,
792+ transformedErrorResponse ,
793+ 'errorResponseSchema' ,
794+ )
795+ }
796+
797+ return rejectWithValue (
798+ transformedErrorResponse ,
799+ addShouldAutoBatch ( { baseQueryMeta : meta } ) ,
800+ )
801+ } catch ( e ) {
802+ caughtError = e
803+ }
729804 }
730- }
731- if (
732- typeof process !== 'undefined' &&
733- process . env . NODE_ENV !== 'production'
734- ) {
735- console . error (
736- `An unhandled error occurred processing a request for the endpoint "${ arg . endpointName } ".
805+ if (
806+ typeof process !== 'undefined' &&
807+ process . env . NODE_ENV !== 'production'
808+ ) {
809+ console . error (
810+ `An unhandled error occurred processing a request for the endpoint "${ arg . endpointName } ".
737811In the case of an unhandled error, no tags will be "provided" or "invalidated".` ,
738- catchedError ,
739- )
740- } else {
741- console . error ( catchedError )
812+ caughtError ,
813+ )
814+ } else {
815+ console . error ( caughtError )
816+ }
817+ throw caughtError
818+ } catch ( error ) {
819+ if ( error instanceof NamedSchemaError ) {
820+ const info : SchemaFailureInfo = {
821+ endpoint : arg . endpointName ,
822+ arg : arg . originalArgs ,
823+ type : arg . type ,
824+ queryCacheKey : arg . type === 'query' ? arg . queryCacheKey : undefined ,
825+ }
826+ endpointDefinition . onSchemaFailure ?.( error , info )
827+ onSchemaFailure ?.( error , info )
828+ }
829+ throw error
742830 }
743- throw catchedError
744831 }
745832 }
746833
0 commit comments