1- import type { Client , ErrorFromErrorMap , ErrorMap , Schema , SchemaInput , SchemaOutput } from '@orpc/contract'
2- import type { Hooks , Value } from '@orpc/shared'
1+ import type { Client , ErrorFromErrorMap , ErrorMap , Meta , ORPCErrorConstructorMap , Schema , SchemaInput , SchemaOutput } from '@orpc/contract'
2+ import type { Interceptor , Value } from '@orpc/shared'
33import type { Context } from './context'
44import type { Lazyable } from './lazy'
55import type { MiddlewareNextFn } from './middleware'
66import type { AnyProcedure , Procedure , ProcedureHandlerOptions } from './procedure'
77import { createORPCErrorConstructorMap , ORPCError , validateORPCError , ValidationError } from '@orpc/contract'
8- import { executeWithHooks , toError , value } from '@orpc/shared'
8+ import { intercept , toError , value } from '@orpc/shared'
99import { unlazy } from './lazy'
1010import { middlewareOutputFn } from './middleware'
1111
@@ -17,34 +17,60 @@ export type ProcedureClient<
1717 TErrorMap extends ErrorMap ,
1818> = Client < TClientContext , SchemaInput < TInputSchema > , SchemaOutput < TOutputSchema , THandlerOutput > , ErrorFromErrorMap < TErrorMap > >
1919
20+ export interface ProcedureClientInterceptorOptions <
21+ TInitialContext extends Context ,
22+ TInputSchema extends Schema ,
23+ TErrorMap extends ErrorMap ,
24+ TMeta extends Meta ,
25+ > {
26+ context : TInitialContext
27+ input : SchemaInput < TInputSchema >
28+ errors : ORPCErrorConstructorMap < TErrorMap >
29+ path : string [ ]
30+ procedure : Procedure < Context , Context , Schema , Schema , unknown , ErrorMap , TMeta >
31+ signal ?: AbortSignal
32+ }
33+
2034/**
2135 * Options for creating a procedure caller with comprehensive type safety
2236 */
2337export type CreateProcedureClientOptions <
2438 TInitialContext extends Context ,
25- TCurrentContext extends Schema ,
26- THandlerOutput extends SchemaInput < TCurrentContext > ,
39+ TInputSchema extends Schema ,
40+ TOutputSchema extends Schema ,
41+ THandlerOutput extends SchemaInput < TOutputSchema > ,
42+ TErrorMap extends ErrorMap ,
43+ TMeta extends Meta ,
2744 TClientContext ,
2845> =
2946 & {
3047 /**
3148 * This is helpful for logging and analytics.
3249 */
3350 path ?: string [ ]
51+
52+ interceptors ?: Interceptor <
53+ ProcedureClientInterceptorOptions < TInitialContext , TInputSchema , TErrorMap , TMeta > ,
54+ SchemaOutput < TOutputSchema , THandlerOutput > ,
55+ ErrorFromErrorMap < TErrorMap >
56+ > [ ]
3457 }
3558 & (
36- | { context : Value < TInitialContext , [ clientContext : TClientContext ] > }
37- | ( Record < never , never > extends TInitialContext ? Record < never , never > : never )
59+ Record < never , never > extends TInitialContext
60+ ? { context ?: Value < TInitialContext , [ clientContext : TClientContext ] > }
61+ : { context : Value < TInitialContext , [ clientContext : TClientContext ] > }
3862 )
39- & Hooks < unknown , SchemaOutput < TCurrentContext , THandlerOutput > , TInitialContext , any >
4063
4164export type CreateProcedureClientRest <
4265 TInitialContext extends Context ,
66+ TInputSchema extends Schema ,
4367 TOutputSchema extends Schema ,
4468 THandlerOutput extends SchemaInput < TOutputSchema > ,
69+ TErrorMap extends ErrorMap ,
70+ TMeta extends Meta ,
4571 TClientContext ,
4672> =
47- | [ options : CreateProcedureClientOptions < TInitialContext , TOutputSchema , THandlerOutput , TClientContext > ]
73+ | [ options : CreateProcedureClientOptions < TInitialContext , TInputSchema , TOutputSchema , THandlerOutput , TErrorMap , TMeta , TClientContext > ]
4874 | ( Record < never , never > extends TInitialContext ? [ ] : never )
4975
5076export function createProcedureClient <
@@ -53,10 +79,19 @@ export function createProcedureClient<
5379 TOutputSchema extends Schema ,
5480 THandlerOutput extends SchemaInput < TOutputSchema > ,
5581 TErrorMap extends ErrorMap ,
82+ TMeta extends Meta ,
5683 TClientContext ,
5784> (
58- lazyableProcedure : Lazyable < Procedure < TInitialContext , any , TInputSchema , TOutputSchema , THandlerOutput , TErrorMap , any > > ,
59- ...[ options ] : CreateProcedureClientRest < TInitialContext , TOutputSchema , THandlerOutput , TClientContext >
85+ lazyableProcedure : Lazyable < Procedure < TInitialContext , any , TInputSchema , TOutputSchema , THandlerOutput , TErrorMap , TMeta > > ,
86+ ...[ options ] : CreateProcedureClientRest <
87+ TInitialContext ,
88+ TInputSchema ,
89+ TOutputSchema ,
90+ THandlerOutput ,
91+ TErrorMap ,
92+ TMeta ,
93+ TClientContext
94+ >
6095) : ProcedureClient < TClientContext , TInputSchema , TOutputSchema , THandlerOutput , TErrorMap > {
6196 return async ( ...[ input , callerOptions ] ) => {
6297 const path = options ?. path ?? [ ]
@@ -65,25 +100,21 @@ export function createProcedureClient<
65100 const context = await value ( options ?. context ?? { } , callerOptions ?. context ) as TInitialContext
66101 const errors = createORPCErrorConstructorMap ( procedure [ '~orpc' ] . errorMap )
67102
68- const executeOptions = {
69- input,
103+ const interceptorOptions : ProcedureClientInterceptorOptions < TInitialContext , TInputSchema , TErrorMap , TMeta > = {
70104 context,
105+ input : input as SchemaInput < TInputSchema > , // input only optional when it undefinable so we can safely cast it
71106 errors,
72107 path,
73108 procedure : procedure as AnyProcedure ,
74109 signal : callerOptions ?. signal ,
75110 }
76111
77112 try {
78- const output = await executeWithHooks ( {
79- hooks : options ,
80- input,
81- context,
82- meta : executeOptions ,
83- execute : ( ) => executeProcedureInternal ( procedure , executeOptions ) ,
84- } )
85-
86- return output
113+ return await intercept (
114+ options ?. interceptors ?? [ ] ,
115+ interceptorOptions ,
116+ interceptorOptions => executeProcedureInternal ( interceptorOptions . procedure , interceptorOptions ) ,
117+ )
87118 }
88119 catch ( e ) {
89120 if ( ! ( e instanceof ORPCError ) ) {
0 commit comments