diff --git a/packages/core/supabase-js/src/index.ts b/packages/core/supabase-js/src/index.ts index 8dd77772d..be8b20255 100644 --- a/packages/core/supabase-js/src/index.ts +++ b/packages/core/supabase-js/src/index.ts @@ -19,7 +19,13 @@ export { } from '@supabase/functions-js' export * from '@supabase/realtime-js' export { default as SupabaseClient } from './SupabaseClient' -export type { SupabaseClientOptions, QueryResult, QueryData, QueryError } from './lib/types' +export type { + SupabaseClientOptions, + QueryResult, + QueryData, + QueryError, + DatabaseWithoutInternals, +} from './lib/types' /** * Creates a new Supabase Client. diff --git a/packages/core/supabase-js/src/lib/types.ts b/packages/core/supabase-js/src/lib/types.ts index 55cea95cd..c4456d943 100644 --- a/packages/core/supabase-js/src/lib/types.ts +++ b/packages/core/supabase-js/src/lib/types.ts @@ -135,3 +135,17 @@ export type SupabaseClientOptions = { export type QueryResult = T extends PromiseLike ? U : never export type QueryData = T extends PromiseLike<{ data: infer U }> ? Exclude : never export type QueryError = PostgrestError + +/** @internal Key used for Supabase internal metadata in Database types. */ +type InternalSupabaseKey = '__InternalSupabase' + +/** + * Strips internal Supabase metadata from Database types. + * Useful for libraries defining generic constraints on Database types. + * + * @example + * ```typescript + * type CleanDB = DatabaseWithoutInternals + * ``` + */ +export type DatabaseWithoutInternals = Omit diff --git a/packages/core/supabase-js/test/types/index.test-d.ts b/packages/core/supabase-js/test/types/index.test-d.ts index 5f4d6713b..654ddb9f4 100644 --- a/packages/core/supabase-js/test/types/index.test-d.ts +++ b/packages/core/supabase-js/test/types/index.test-d.ts @@ -1,5 +1,10 @@ import { expectError, expectType } from 'tsd' -import { PostgrestSingleResponse, SupabaseClient, createClient } from '../../src/index' +import { + PostgrestSingleResponse, + SupabaseClient, + createClient, + DatabaseWithoutInternals, +} from '../../src/index' import { Database, Json } from '../types' const URL = 'http://localhost:3000' @@ -265,3 +270,42 @@ const supabase = createClient(URL, KEY) // @ts-expect-error should raise error if providing table name not in the schema pg13CustomSchemaClient.from('channels_details') } + +// DatabaseWithoutInternals utility type +{ + type TestDatabaseWithInternals = { + __InternalSupabase: { + PostgrestVersion: '14' + } + public: { + Tables: { + users: { + Row: { id: number } + Insert: { id: number } + Update: { id?: number } + Relationships: [] + } + } + Views: { [_ in never]: never } + Functions: { [_ in never]: never } + Enums: { [_ in never]: never } + CompositeTypes: { [_ in never]: never } + } + } + + type CleanedDatabase = DatabaseWithoutInternals + + // Should have 'public' schema + expectType({} as TestDatabaseWithInternals['public']) + + // Should not have '__InternalSupabase' key + type HasInternalKey = '__InternalSupabase' extends keyof CleanedDatabase ? true : false + expectType(false) + + // Should work with databases that don't have __InternalSupabase + type PlainDatabase = { + public: { Tables: {}; Views: {}; Functions: {}; Enums: {}; CompositeTypes: {} } + } + type CleanedPlainDatabase = DatabaseWithoutInternals + expectType({} as PlainDatabase) +}