|
| 1 | +import type { GenericFunction, GenericSchema, GenericSetofOption } from './common' |
| 2 | + |
| 3 | +// Functions matching utils |
| 4 | +type IsMatchingArgs< |
| 5 | + FnArgs extends GenericFunction['Args'], |
| 6 | + PassedArgs extends GenericFunction['Args'], |
| 7 | +> = [FnArgs] extends [Record<PropertyKey, never>] |
| 8 | + ? PassedArgs extends Record<PropertyKey, never> |
| 9 | + ? true |
| 10 | + : false |
| 11 | + : keyof PassedArgs extends keyof FnArgs |
| 12 | + ? PassedArgs extends FnArgs |
| 13 | + ? true |
| 14 | + : false |
| 15 | + : false |
| 16 | + |
| 17 | +type MatchingFunctionArgs< |
| 18 | + Fn extends GenericFunction, |
| 19 | + Args extends GenericFunction['Args'], |
| 20 | +> = Fn extends { Args: infer A extends GenericFunction['Args'] } |
| 21 | + ? IsMatchingArgs<A, Args> extends true |
| 22 | + ? Fn |
| 23 | + : never |
| 24 | + : false |
| 25 | + |
| 26 | +type FindMatchingFunctionByArgs< |
| 27 | + FnUnion, |
| 28 | + Args extends GenericFunction['Args'], |
| 29 | +> = FnUnion extends infer Fn extends GenericFunction ? MatchingFunctionArgs<Fn, Args> : false |
| 30 | + |
| 31 | +// Types for working with database schemas |
| 32 | +type TablesAndViews<Schema extends GenericSchema> = Schema['Tables'] & Exclude<Schema['Views'], ''> |
| 33 | + |
| 34 | +// Utility types for working with unions |
| 35 | +type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void |
| 36 | + ? I |
| 37 | + : never |
| 38 | + |
| 39 | +type LastOf<T> = |
| 40 | + UnionToIntersection<T extends any ? () => T : never> extends () => infer R ? R : never |
| 41 | + |
| 42 | +type IsAny<T> = 0 extends 1 & T ? true : false |
| 43 | + |
| 44 | +type ExactMatch<T, S> = [T] extends [S] ? ([S] extends [T] ? true : false) : false |
| 45 | + |
| 46 | +type ExtractExactFunction<Fns, Args> = Fns extends infer F |
| 47 | + ? F extends GenericFunction |
| 48 | + ? ExactMatch<F['Args'], Args> extends true |
| 49 | + ? F |
| 50 | + : never |
| 51 | + : never |
| 52 | + : never |
| 53 | + |
| 54 | +type IsNever<T> = [T] extends [never] ? true : false |
| 55 | + |
| 56 | +type RpcFunctionNotFound<FnName> = { |
| 57 | + Row: any |
| 58 | + Result: { |
| 59 | + error: true |
| 60 | + } & "Couldn't infer function definition matching provided arguments" |
| 61 | + RelationName: FnName |
| 62 | + Relationships: null |
| 63 | +} |
| 64 | + |
| 65 | +export type GetRpcFunctionFilterBuilderByArgs< |
| 66 | + Schema extends GenericSchema, |
| 67 | + FnName extends string & keyof Schema['Functions'], |
| 68 | + Args, |
| 69 | +> = { |
| 70 | + 0: Schema['Functions'][FnName] |
| 71 | + // If the Args is exactly never (function call without any params) |
| 72 | + 1: IsAny<Schema> extends true |
| 73 | + ? any |
| 74 | + : IsNever<Args> extends true |
| 75 | + ? // This is for retro compatibility, if the funcition is defined with an single return and an union of Args |
| 76 | + // we fallback to the last function definition matched by name |
| 77 | + IsNever<ExtractExactFunction<Schema['Functions'][FnName], Args>> extends true |
| 78 | + ? LastOf<Schema['Functions'][FnName]> |
| 79 | + : ExtractExactFunction<Schema['Functions'][FnName], Args> |
| 80 | + : Args extends Record<PropertyKey, never> |
| 81 | + ? LastOf<Schema['Functions'][FnName]> |
| 82 | + : // Otherwise, we attempt to match with one of the function definition in the union based |
| 83 | + // on the function arguments provided |
| 84 | + Args extends GenericFunction['Args'] |
| 85 | + ? // This is for retro compatibility, if the funcition is defined with an single return and an union of Args |
| 86 | + // we fallback to the last function definition matched by name |
| 87 | + IsNever< |
| 88 | + LastOf<FindMatchingFunctionByArgs<Schema['Functions'][FnName], Args>> |
| 89 | + > extends true |
| 90 | + ? LastOf<Schema['Functions'][FnName]> |
| 91 | + : // Otherwise, we use the arguments based function definition narrowing to get the right value |
| 92 | + LastOf<FindMatchingFunctionByArgs<Schema['Functions'][FnName], Args>> |
| 93 | + : // If we can't find a matching function by args, we try to find one by function name |
| 94 | + ExtractExactFunction<Schema['Functions'][FnName], Args> extends GenericFunction |
| 95 | + ? ExtractExactFunction<Schema['Functions'][FnName], Args> |
| 96 | + : any |
| 97 | +}[1] extends infer Fn |
| 98 | + ? // If we are dealing with an non-typed client everything is any |
| 99 | + IsAny<Fn> extends true |
| 100 | + ? { Row: any; Result: any; RelationName: FnName; Relationships: null } |
| 101 | + : // Otherwise, we use the arguments based function definition narrowing to get the rigt value |
| 102 | + Fn extends GenericFunction |
| 103 | + ? { |
| 104 | + Row: Fn['SetofOptions'] extends GenericSetofOption |
| 105 | + ? Fn['SetofOptions']['isSetofReturn'] extends true |
| 106 | + ? TablesAndViews<Schema>[Fn['SetofOptions']['to']]['Row'] |
| 107 | + : TablesAndViews<Schema>[Fn['SetofOptions']['to']]['Row'] |
| 108 | + : Fn['Returns'] extends any[] |
| 109 | + ? Fn['Returns'][number] extends Record<string, unknown> |
| 110 | + ? Fn['Returns'][number] |
| 111 | + : never |
| 112 | + : Fn['Returns'] extends Record<string, unknown> |
| 113 | + ? Fn['Returns'] |
| 114 | + : never |
| 115 | + Result: Fn['SetofOptions'] extends GenericSetofOption |
| 116 | + ? Fn['SetofOptions']['isSetofReturn'] extends true |
| 117 | + ? Fn['SetofOptions']['isOneToOne'] extends true |
| 118 | + ? Fn['Returns'][] |
| 119 | + : Fn['Returns'] |
| 120 | + : Fn['Returns'] |
| 121 | + : Fn['Returns'] |
| 122 | + RelationName: Fn['SetofOptions'] extends GenericSetofOption |
| 123 | + ? Fn['SetofOptions']['to'] |
| 124 | + : FnName |
| 125 | + Relationships: Fn['SetofOptions'] extends GenericSetofOption |
| 126 | + ? Fn['SetofOptions']['to'] extends keyof Schema['Tables'] |
| 127 | + ? Schema['Tables'][Fn['SetofOptions']['to']]['Relationships'] |
| 128 | + : Schema['Views'][Fn['SetofOptions']['to']]['Relationships'] |
| 129 | + : null |
| 130 | + } |
| 131 | + : // If we failed to find the function by argument, we still pass with any but also add an overridable |
| 132 | + Fn extends false |
| 133 | + ? RpcFunctionNotFound<FnName> |
| 134 | + : RpcFunctionNotFound<FnName> |
| 135 | + : RpcFunctionNotFound<FnName> |
0 commit comments