From cc7276481118f7241bf277f3dce80050a230df1b Mon Sep 17 00:00:00 2001 From: avallete Date: Tue, 7 Oct 2025 13:03:30 +0200 Subject: [PATCH 1/2] refactor(supabase): reduce codedup between PostgrestClient and SupabaseClient leverage inference We currently duplicate a lot of the typing logic between postgrest-js and supabase-js This makes it very hard to change anything type-wise in postgrest-js without needing to update supabase-js as well. This is mainly because we re-declare functions type returns instead of relying over return type inference. With this change, as long as the arguments passed to a rest function don't change, the result type will be infered from the this.rest call. This will allows postgrest-js to alter the result types / implementation details without having to duplicate all changes over to supabase-js. --- .../core/supabase-js/src/SupabaseClient.ts | 77 ++++++++----------- 1 file changed, 31 insertions(+), 46 deletions(-) diff --git a/packages/core/supabase-js/src/SupabaseClient.ts b/packages/core/supabase-js/src/SupabaseClient.ts index 0526ef3cd..cee995249 100644 --- a/packages/core/supabase-js/src/SupabaseClient.ts +++ b/packages/core/supabase-js/src/SupabaseClient.ts @@ -1,27 +1,28 @@ +import type { AuthChangeEvent } from '@supabase/auth-js' import { FunctionsClient } from '@supabase/functions-js' -import { AuthChangeEvent } from '@supabase/auth-js' +import { PostgrestClient } from '@supabase/postgrest-js' import { - PostgrestClient, - PostgrestFilterBuilder, - PostgrestQueryBuilder, -} from '@supabase/postgrest-js' -import { - RealtimeChannel, - RealtimeChannelOptions, + type RealtimeChannel, + type RealtimeChannelOptions, RealtimeClient, - RealtimeClientOptions, + type RealtimeClientOptions, } from '@supabase/realtime-js' import { StorageClient as SupabaseStorageClient } from '@supabase/storage-js' import { - DEFAULT_GLOBAL_OPTIONS, - DEFAULT_DB_OPTIONS, DEFAULT_AUTH_OPTIONS, + DEFAULT_DB_OPTIONS, + DEFAULT_GLOBAL_OPTIONS, DEFAULT_REALTIME_OPTIONS, } from './lib/constants' import { fetchWithAuth } from './lib/fetch' import { applySettingDefaults, validateSupabaseUrl } from './lib/helpers' import { SupabaseAuthClient } from './lib/SupabaseAuthClient' -import { Fetch, GenericSchema, SupabaseClientOptions, SupabaseAuthClientOptions } from './lib/types' +import type { + Fetch, + GenericSchema, + SupabaseAuthClientOptions, + SupabaseClientOptions, +} from './lib/types' /** * Supabase Client. @@ -178,20 +179,14 @@ export default class SupabaseClient< }) } - // NOTE: signatures must be kept in sync with PostgrestClient.from - from< - TableName extends string & keyof Schema['Tables'], - Table extends Schema['Tables'][TableName], - >(relation: TableName): PostgrestQueryBuilder - from( - relation: ViewName - ): PostgrestQueryBuilder /** * Perform a query on a table or a view. * * @param relation - The table or view name to query */ - from(relation: string): PostgrestQueryBuilder { + from( + relation: RelationName + ) { return this.rest.from(relation) } @@ -205,13 +200,8 @@ export default class SupabaseClient< */ schema>( schema: DynamicSchema - ): PostgrestClient< - Database, - ClientOptions, - DynamicSchema, - Database[DynamicSchema] extends GenericSchema ? Database[DynamicSchema] : any - > { - return this.rest.schema(schema) + ) { + return this.rest.schema(schema) } // NOTE: signatures must be kept in sync with PostgrestClient.rpc @@ -238,27 +228,22 @@ export default class SupabaseClient< * `"estimated"`: Uses exact count for low numbers and planned count for high * numbers. */ - rpc( + rpc< + FnName extends string & keyof Schema['Functions'], + Args extends Schema['Functions'][FnName]['Args'] = never, + >( fn: FnName, - args: Fn['Args'] = {}, + args: Args = {} as Args, options: { head?: boolean get?: boolean count?: 'exact' | 'planned' | 'estimated' - } = {} - ): PostgrestFilterBuilder< - ClientOptions, - Schema, - Fn['Returns'] extends any[] - ? Fn['Returns'][number] extends Record - ? Fn['Returns'][number] - : never - : never, - Fn['Returns'], - FnName, - null, - 'RPC' - > { + } = { + head: false, + get: false, + count: undefined, + } + ) { return this.rest.rpc(fn, args, options) } @@ -355,7 +340,7 @@ export default class SupabaseClient< } private _listenForAuthEvents() { - let data = this.auth.onAuthStateChange((event, session) => { + const data = this.auth.onAuthStateChange((event, session) => { this._handleTokenChanged(event, 'CLIENT', session?.access_token) }) return data @@ -374,7 +359,7 @@ export default class SupabaseClient< this.realtime.setAuth(token) } else if (event === 'SIGNED_OUT') { this.realtime.setAuth() - if (source == 'STORAGE') this.auth.signOut() + if (source === 'STORAGE') this.auth.signOut() this.changedAccessToken = undefined } } From 99dad2e8c81b9d39a9e2f87f9c2bad3bdc718a88 Mon Sep 17 00:00:00 2001 From: avallete Date: Tue, 7 Oct 2025 13:20:08 +0200 Subject: [PATCH 2/2] chore(supabase): skip slow-types for rest inference --- packages/core/supabase-js/src/SupabaseClient.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/core/supabase-js/src/SupabaseClient.ts b/packages/core/supabase-js/src/SupabaseClient.ts index cee995249..6bc312122 100644 --- a/packages/core/supabase-js/src/SupabaseClient.ts +++ b/packages/core/supabase-js/src/SupabaseClient.ts @@ -184,6 +184,7 @@ export default class SupabaseClient< * * @param relation - The table or view name to query */ + // @jsr-ignore slow-type-missing-explicit-return-type from( relation: RelationName ) { @@ -198,6 +199,7 @@ export default class SupabaseClient< * * @param schema - The schema to query */ + // @jsr-ignore slow-type-missing-explicit-return-type schema>( schema: DynamicSchema ) { @@ -228,6 +230,7 @@ export default class SupabaseClient< * `"estimated"`: Uses exact count for low numbers and planned count for high * numbers. */ + // @jsr-ignore slow-type-missing-explicit-return-type rpc< FnName extends string & keyof Schema['Functions'], Args extends Schema['Functions'][FnName]['Args'] = never,