@@ -205,7 +205,7 @@ export type ResolveRelationship<
205205 Schema extends GenericSchema ,
206206 Relationships extends GenericRelationship [ ] ,
207207 Field extends Ast . FieldNode ,
208- CurrentTableOrView extends keyof TablesAndViews < Schema >
208+ CurrentTableOrView extends keyof TablesAndViews < Schema > & string
209209> = ResolveReverseRelationship <
210210 Schema ,
211211 Relationships ,
@@ -385,7 +385,7 @@ type FilterRelationships<R, TName, From> = R extends readonly (infer Rel)[]
385385type ResolveForwardRelationship <
386386 Schema extends GenericSchema ,
387387 Field extends Ast . FieldNode ,
388- CurrentTableOrView extends keyof TablesAndViews < Schema >
388+ CurrentTableOrView extends keyof TablesAndViews < Schema > & string
389389> = FindFieldMatchingRelationships <
390390 Schema ,
391391 TablesAndViews < Schema > [ Field [ 'name' ] ] [ 'Relationships' ] ,
@@ -413,9 +413,58 @@ type ResolveForwardRelationship<
413413 relation : FoundByMatch
414414 direction : 'forward'
415415 from : CurrentTableOrView
416- type : 'found-my-match'
416+ type : 'found-by-match'
417+ }
418+ : // Forward relations can also alias other tables via tables joins relationships
419+ // in such cases we crawl all the tables looking for a join table between our current table
420+ // and the Field['name'] desired desitnation
421+ FindJoinTableRelationship <
422+ Schema ,
423+ CurrentTableOrView ,
424+ Field [ 'name' ]
425+ > extends infer FoundByJoinTable extends GenericRelationship
426+ ? {
427+ referencedTable : TablesAndViews < Schema > [ FoundByJoinTable [ 'referencedRelation' ] ]
428+ relation : FoundByJoinTable & { match : 'refrel' }
429+ direction : 'forward'
430+ from : CurrentTableOrView
431+ type : 'found-by-join-table'
417432 }
418- : SelectQueryError < 'could not find the relation' >
433+ : SelectQueryError < `could not find the relation between ${CurrentTableOrView } and ${Field [ 'name' ] } `>
434+
435+ /**
436+ * Given a CurrentTableOrView, finds all join tables to this relation.
437+ * For example, if products and categories are linked via product_categories table:
438+ *
439+ * @example
440+ * Given:
441+ * - CurrentTableView = 'products'
442+ * - FieldName = "categories"
443+ *
444+ * It should return this relationship from product_categories:
445+ * {
446+ * foreignKeyName: "product_categories_category_id_fkey",
447+ * columns: ["category_id"],
448+ * isOneToOne: false,
449+ * referencedRelation: "categories",
450+ * referencedColumns: ["id"]
451+ * }
452+ */
453+ export type FindJoinTableRelationship <
454+ Schema extends GenericSchema ,
455+ CurrentTableOrView extends keyof TablesAndViews < Schema > & string ,
456+ FieldName extends string
457+ > = {
458+ [ TableName in keyof TablesAndViews < Schema > ] : TablesAndViews < Schema > [ TableName ] [ 'Relationships' ] extends readonly ( infer Rel ) [ ]
459+ ? Rel extends { referencedRelation : CurrentTableOrView }
460+ ? TablesAndViews < Schema > [ TableName ] [ 'Relationships' ] extends readonly ( infer OtherRel ) [ ]
461+ ? OtherRel extends { referencedRelation : FieldName }
462+ ? OtherRel
463+ : never
464+ : never
465+ : never
466+ : never
467+ } [ keyof TablesAndViews < Schema > ]
419468
420469/**
421470 * Finds a matching relationship based on the FieldNode's name and optional hint.
0 commit comments