Skip to content

Commit e76a0af

Browse files
committed
Handle column name embed
1 parent 32e220c commit e76a0af

File tree

2 files changed

+78
-29
lines changed

2 files changed

+78
-29
lines changed

src/select-query-parser.ts

+54-29
Original file line numberDiff line numberDiff line change
@@ -66,25 +66,34 @@ type EatWhitespace<Input extends string> = string extends Input
6666
? EatWhitespace<Remainder>
6767
: Input
6868

69-
type HasFKey<FKeyName, Relationships> = Relationships extends [infer R]
70-
? R extends { foreignKeyName: FKeyName }
69+
type InArray<Item, Array> = Array extends [infer I]
70+
? I extends Item
7171
? true
7272
: false
73-
: Relationships extends [infer R, ...infer Rest]
74-
? HasFKey<FKeyName, [R]> extends true
73+
: Array extends [infer I, ...infer Rest]
74+
? InArray<Item, [I]> extends true
7575
? true
76-
: HasFKey<FKeyName, Rest>
76+
: InArray<Item, Rest>
7777
: false
7878

79-
type HasFKeyToFRel<FRelName, Relationships> = Relationships extends [infer R]
80-
? R extends { referencedRelation: FRelName }
81-
? true
82-
: false
79+
type HasFKey<FKeyName, Relationships> = InArray<{ foreignKeyName: FKeyName }, Relationships>
80+
81+
type HasFKeyToFRel<FRelName, Relationships> = InArray<
82+
{ referencedRelation: FRelName },
83+
Relationships
84+
>
85+
86+
type ColumnForeignRelation<ColName, Relationships> = Relationships extends [infer R]
87+
? R extends { columns: string[]; referencedRelation: string }
88+
? InArray<ColName, R['columns']> extends true
89+
? [R['referencedRelation']]
90+
: null
91+
: null
8392
: Relationships extends [infer R, ...infer Rest]
84-
? HasFKeyToFRel<FRelName, [R]> extends true
85-
? true
86-
: HasFKeyToFRel<FRelName, Rest>
87-
: false
93+
? ColumnForeignRelation<ColName, [R]> extends [infer Rel]
94+
? [Rel]
95+
: ColumnForeignRelation<ColName, Rest>
96+
: null
8897

8998
/**
9099
* Constructs a type definition for a single field of an object.
@@ -119,23 +128,39 @@ type ConstructFieldDefinition<
119128
: never
120129
}
121130
: Field extends { name: string; original: string; children: unknown[] }
122-
? {
123-
[_ in Field['name']]: GetResultHelper<
124-
Schema,
125-
(Schema['Tables'] & Schema['Views'])[Field['original']]['Row'],
126-
(Schema['Tables'] & Schema['Views'])[Field['original']] extends { Relationships: infer R }
127-
? R
128-
: unknown,
129-
Field['children'],
130-
unknown
131-
> extends infer Child
132-
? Relationships extends unknown[]
133-
? HasFKeyToFRel<Field['original'], Relationships> extends true
134-
? Child | null
131+
? ColumnForeignRelation<Field['original'], Relationships> extends [infer ForeignRel]
132+
? // handle `col:foreign_key_column`
133+
ForeignRel extends keyof (Schema['Tables'] & Schema['Views'])
134+
? {
135+
[_ in Field['name']]: GetResultHelper<
136+
Schema,
137+
(Schema['Tables'] & Schema['Views'])[ForeignRel]['Row'],
138+
(Schema['Tables'] & Schema['Views'])[ForeignRel] extends { Relationships: infer R }
139+
? R
140+
: unknown,
141+
Field['children'],
142+
unknown
143+
> | null
144+
}
145+
: SelectQueryError<`Unknown relation in a relationship`>
146+
: // handle `col:relation`
147+
{
148+
[_ in Field['name']]: GetResultHelper<
149+
Schema,
150+
(Schema['Tables'] & Schema['Views'])[Field['original']]['Row'],
151+
(Schema['Tables'] & Schema['Views'])[Field['original']] extends { Relationships: infer R }
152+
? R
153+
: unknown,
154+
Field['children'],
155+
unknown
156+
> extends infer Child
157+
? Relationships extends unknown[]
158+
? HasFKeyToFRel<Field['original'], Relationships> extends true
159+
? Child | null
160+
: Child[]
135161
: Child[]
136-
: Child[]
137-
: never
138-
}
162+
: never
163+
}
139164
: Field extends { name: string; original: string }
140165
? Field['original'] extends keyof Row
141166
? { [K in Field['name']]: Row[Field['original']] }

test/index.test-d.ts

+24
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,30 @@ const postgrest = new PostgrestClient<Database>(REST_URL)
7474
expectType<Database['public']['Tables']['users']['Row'] | null>(message.user)
7575
}
7676

77+
// many-to-one relationship (fkey)
78+
{
79+
const { data: message, error } = await postgrest
80+
.from('messages')
81+
.select('user:users!messages_username_fkey(*)')
82+
.single()
83+
if (error) {
84+
throw new Error(error.message)
85+
}
86+
expectType<Database['public']['Tables']['users']['Row'] | null>(message.user)
87+
}
88+
89+
// many-to-one relationship (column name)
90+
{
91+
const { data: message, error } = await postgrest
92+
.from('messages')
93+
.select('user:username(*)')
94+
.single()
95+
if (error) {
96+
throw new Error(error.message)
97+
}
98+
expectType<Database['public']['Tables']['users']['Row'] | null>(message.user)
99+
}
100+
77101
// one-to-many relationship
78102
{
79103
const { data: user, error } = await postgrest.from('users').select('messages(*)').single()

0 commit comments

Comments
 (0)