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'
3
3
import type { Context } from './context'
4
4
import type { Lazyable } from './lazy'
5
5
import type { MiddlewareNextFn } from './middleware'
6
6
import type { AnyProcedure , Procedure , ProcedureHandlerOptions } from './procedure'
7
7
import { createORPCErrorConstructorMap , ORPCError , validateORPCError , ValidationError } from '@orpc/contract'
8
- import { executeWithHooks , toError , value } from '@orpc/shared'
8
+ import { intercept , toError , value } from '@orpc/shared'
9
9
import { unlazy } from './lazy'
10
10
import { middlewareOutputFn } from './middleware'
11
11
@@ -17,34 +17,60 @@ export type ProcedureClient<
17
17
TErrorMap extends ErrorMap ,
18
18
> = Client < TClientContext , SchemaInput < TInputSchema > , SchemaOutput < TOutputSchema , THandlerOutput > , ErrorFromErrorMap < TErrorMap > >
19
19
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
+
20
34
/**
21
35
* Options for creating a procedure caller with comprehensive type safety
22
36
*/
23
37
export type CreateProcedureClientOptions <
24
38
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 ,
27
44
TClientContext ,
28
45
> =
29
46
& {
30
47
/**
31
48
* This is helpful for logging and analytics.
32
49
*/
33
50
path ?: string [ ]
51
+
52
+ interceptors ?: Interceptor <
53
+ ProcedureClientInterceptorOptions < TInitialContext , TInputSchema , TErrorMap , TMeta > ,
54
+ SchemaOutput < TOutputSchema , THandlerOutput > ,
55
+ ErrorFromErrorMap < TErrorMap >
56
+ > [ ]
34
57
}
35
58
& (
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 ] > }
38
62
)
39
- & Hooks < unknown , SchemaOutput < TCurrentContext , THandlerOutput > , TInitialContext , any >
40
63
41
64
export type CreateProcedureClientRest <
42
65
TInitialContext extends Context ,
66
+ TInputSchema extends Schema ,
43
67
TOutputSchema extends Schema ,
44
68
THandlerOutput extends SchemaInput < TOutputSchema > ,
69
+ TErrorMap extends ErrorMap ,
70
+ TMeta extends Meta ,
45
71
TClientContext ,
46
72
> =
47
- | [ options : CreateProcedureClientOptions < TInitialContext , TOutputSchema , THandlerOutput , TClientContext > ]
73
+ | [ options : CreateProcedureClientOptions < TInitialContext , TInputSchema , TOutputSchema , THandlerOutput , TErrorMap , TMeta , TClientContext > ]
48
74
| ( Record < never , never > extends TInitialContext ? [ ] : never )
49
75
50
76
export function createProcedureClient <
@@ -53,10 +79,19 @@ export function createProcedureClient<
53
79
TOutputSchema extends Schema ,
54
80
THandlerOutput extends SchemaInput < TOutputSchema > ,
55
81
TErrorMap extends ErrorMap ,
82
+ TMeta extends Meta ,
56
83
TClientContext ,
57
84
> (
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
+ >
60
95
) : ProcedureClient < TClientContext , TInputSchema , TOutputSchema , THandlerOutput , TErrorMap > {
61
96
return async ( ...[ input , callerOptions ] ) => {
62
97
const path = options ?. path ?? [ ]
@@ -65,25 +100,21 @@ export function createProcedureClient<
65
100
const context = await value ( options ?. context ?? { } , callerOptions ?. context ) as TInitialContext
66
101
const errors = createORPCErrorConstructorMap ( procedure [ '~orpc' ] . errorMap )
67
102
68
- const executeOptions = {
69
- input,
103
+ const interceptorOptions : ProcedureClientInterceptorOptions < TInitialContext , TInputSchema , TErrorMap , TMeta > = {
70
104
context,
105
+ input : input as SchemaInput < TInputSchema > , // input only optional when it undefinable so we can safely cast it
71
106
errors,
72
107
path,
73
108
procedure : procedure as AnyProcedure ,
74
109
signal : callerOptions ?. signal ,
75
110
}
76
111
77
112
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
+ )
87
118
}
88
119
catch ( e ) {
89
120
if ( ! ( e instanceof ORPCError ) ) {
0 commit comments