@@ -2,8 +2,80 @@ import PostgrestQueryBuilder from './PostgrestQueryBuilder'
22import PostgrestFilterBuilder from './PostgrestFilterBuilder'
33import PostgrestBuilder from './PostgrestBuilder'
44import { DEFAULT_HEADERS } from './constants'
5- import { Fetch , GenericSchema , GenericSetofOption } from './types'
6- import { IsAny } from './select-query-parser/utils'
5+ import { Fetch , GenericFunction , GenericSchema , GenericSetofOption } from './types'
6+ import { FindMatchingFunctionByArgs , IsAny } from './select-query-parser/utils'
7+
8+ type ExactMatch < T , S > = [ T ] extends [ S ] ? ( [ S ] extends [ T ] ? true : false ) : false
9+
10+ type ExtractExactFunction < Fns , Args > = Fns extends infer F
11+ ? F extends GenericFunction
12+ ? ExactMatch < F [ 'Args' ] , Args > extends true
13+ ? F
14+ : never
15+ : never
16+ : never
17+
18+ export type GetRpcFunctionFilterBuilderByArgs <
19+ Schema extends GenericSchema ,
20+ FnName extends string & keyof Schema [ 'Functions' ] ,
21+ Args
22+ > = {
23+ 0 : Schema [ 'Functions' ] [ FnName ]
24+ // This is here to handle the case where the args is exactly {} and fallback to the empty
25+ // args function definition if there is one in such case
26+ 1 : [ keyof Args ] extends [ never ]
27+ ? ExtractExactFunction < Schema [ 'Functions' ] [ FnName ] , Args >
28+ : Args extends GenericFunction [ 'Args' ]
29+ ? FindMatchingFunctionByArgs < Schema [ 'Functions' ] [ FnName ] , Args >
30+ : any
31+ } [ 1 ] extends infer Fn
32+ ? IsAny < Fn > extends true
33+ ? { Row : any ; Result : any ; RelationName : FnName ; Relationships : null }
34+ : Fn extends GenericFunction
35+ ? {
36+ Row : Fn [ 'Returns' ] extends any [ ]
37+ ? Fn [ 'Returns' ] [ number ] extends Record < string , unknown >
38+ ? Fn [ 'Returns' ] [ number ]
39+ : never
40+ : Fn [ 'Returns' ] extends Record < string , unknown >
41+ ? Fn [ 'Returns' ]
42+ : never
43+ Result : Fn [ 'Returns' ]
44+ RelationName : Fn [ 'SetofOptions' ] extends GenericSetofOption
45+ ? Fn [ 'SetofOptions' ] [ 'to' ]
46+ : FnName
47+ Relationships : Fn [ 'SetofOptions' ] extends GenericSetofOption
48+ ? Fn [ 'SetofOptions' ] [ 'to' ] extends keyof Schema [ 'Tables' ]
49+ ? Schema [ 'Tables' ] [ Fn [ 'SetofOptions' ] [ 'to' ] ] [ 'Relationships' ]
50+ : Schema [ 'Views' ] [ Fn [ 'SetofOptions' ] [ 'to' ] ] [ 'Relationships' ]
51+ : null
52+ }
53+ : Fn extends never
54+ ? {
55+ Row : any
56+ Result : { error : true } & "Couldn't find function"
57+ RelationName : FnName
58+ Relationships : null
59+ }
60+ : never
61+ : never
62+
63+ export type RpcRowType <
64+ Schema extends GenericSchema ,
65+ FnName extends string & keyof Schema [ 'Functions' ] ,
66+ Args
67+ > = {
68+ 0 : Schema [ 'Functions' ] [ FnName ]
69+ 1 : Args extends GenericFunction [ 'Args' ]
70+ ? FindMatchingFunctionByArgs < Schema [ 'Functions' ] [ FnName ] , Args >
71+ : any
72+ } [ 1 ] extends infer Fn
73+ ? IsAny < Fn > extends true
74+ ? any
75+ : Fn extends GenericFunction
76+ ? Fn [ 'Returns' ]
77+ : never
78+ : never
779
880/**
981 * PostgREST client.
@@ -122,9 +194,17 @@ export default class PostgrestClient<
122194 * `"estimated"`: Uses exact count for low numbers and planned count for high
123195 * numbers.
124196 */
125- rpc < FnName extends string & keyof Schema [ 'Functions' ] , Fn extends Schema [ 'Functions' ] [ FnName ] > (
197+ rpc <
198+ FnName extends string & keyof Schema [ 'Functions' ] ,
199+ Args extends Schema [ 'Functions' ] [ FnName ] [ 'Args' ] = { } ,
200+ FilterBuilder extends GetRpcFunctionFilterBuilderByArgs <
201+ Schema ,
202+ FnName ,
203+ Args
204+ > = GetRpcFunctionFilterBuilderByArgs < Schema , FnName , Args >
205+ > (
126206 fn : FnName ,
127- args : Fn [ ' Args' ] = { } ,
207+ args : Args = { } as Args ,
128208 {
129209 head = false ,
130210 get = false ,
@@ -134,39 +214,13 @@ export default class PostgrestClient<
134214 get ?: boolean
135215 count ?: 'exact' | 'planned' | 'estimated'
136216 } = { }
137- // if rpc is called with a typeless client, default to infering everything as any
138- ) : IsAny < Fn > extends true
139- ? PostgrestFilterBuilder <
140- Schema ,
141- Fn [ 'Returns' ] extends any [ ]
142- ? Fn [ 'Returns' ] [ number ] extends Record < string , unknown >
143- ? Fn [ 'Returns' ] [ number ]
144- : never
145- : Fn [ 'Returns' ] extends Record < string , unknown >
146- ? Fn [ 'Returns' ]
147- : never ,
148- Fn [ 'Returns' ] ,
149- FnName ,
150- null
151- >
152- : PostgrestFilterBuilder <
153- // otherwise, provide the right params for typed .select chaining
154- Schema ,
155- Fn [ 'Returns' ] extends any [ ]
156- ? Fn [ 'Returns' ] [ number ] extends Record < string , unknown >
157- ? Fn [ 'Returns' ] [ number ]
158- : never
159- : Fn [ 'Returns' ] extends Record < string , unknown >
160- ? Fn [ 'Returns' ]
161- : never ,
162- Fn [ 'Returns' ] ,
163- Fn [ 'SetofOptions' ] extends GenericSetofOption ? Fn [ 'SetofOptions' ] [ 'to' ] : FnName ,
164- Fn [ 'SetofOptions' ] extends GenericSetofOption
165- ? Fn [ 'SetofOptions' ] [ 'to' ] extends keyof Schema [ 'Tables' ]
166- ? Schema [ 'Tables' ] [ Fn [ 'SetofOptions' ] [ 'to' ] ] [ 'Relationships' ]
167- : Schema [ 'Views' ] [ Fn [ 'SetofOptions' ] [ 'to' ] ] [ 'Relationships' ]
168- : null
169- > {
217+ ) : PostgrestFilterBuilder <
218+ Schema ,
219+ FilterBuilder [ 'Row' ] ,
220+ FilterBuilder [ 'Result' ] ,
221+ FilterBuilder [ 'RelationName' ] ,
222+ FilterBuilder [ 'Relationships' ]
223+ > {
170224 let method : 'HEAD' | 'GET' | 'POST'
171225 const url = new URL ( `${ this . url } /rpc/${ fn } ` )
172226 let body : unknown | undefined
@@ -199,6 +253,6 @@ export default class PostgrestClient<
199253 body,
200254 fetch : this . fetch ,
201255 allowEmpty : false ,
202- } as unknown as PostgrestBuilder < Fn [ 'Returns '] > )
256+ } as unknown as PostgrestBuilder < FilterBuilder [ 'Row '] > )
203257 }
204258}
0 commit comments