From c5ee251d0fe1eadb544d27ef57c7e86537653ae0 Mon Sep 17 00:00:00 2001 From: Bobbie Soedirgo Date: Wed, 20 Aug 2025 01:42:18 +0800 Subject: [PATCH 1/5] feat: reland postgrest 13 support --- package-lock.json | 38 ++++++++++++++++++++++++++------- package.json | 2 +- src/SupabaseClient.ts | 43 +++++++++++++++++++++++++++++--------- src/index.ts | 24 ++++++++++++++------- test/types/index.test-d.ts | 8 ++++++- 5 files changed, 88 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1149220f..d5a69174 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@supabase/auth-js": "2.71.1", "@supabase/functions-js": "2.4.5", "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "1.19.4", + "@supabase/postgrest-js": "file:../postgrest-js", "@supabase/realtime-js": "2.15.1", "@supabase/storage-js": "^2.10.4" }, @@ -40,6 +40,33 @@ "webpack-cli": "^4.9.2" } }, + "../postgrest-js": { + "name": "@supabase/postgrest-js", + "version": "0.0.0-automated", + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + }, + "devDependencies": { + "@types/jest": "^27.5.1", + "chokidar-cli": "^3.0.0", + "cpy-cli": "^5.0.0", + "jest": "^28.1.0", + "node-abort-controller": "^3.0.1", + "npm-run-all": "^4.1.5", + "prettier": "^2.6.2", + "rimraf": "^3.0.2", + "semantic-release-plugin-update-version-in-files": "^1.1.0", + "ts-expect": "^1.3.0", + "ts-jest": "^28.0.3", + "tsd": "^0.31.2", + "type-fest": "^4.32.0", + "typedoc": "^0.22.16", + "typescript": "^4.5.5", + "wait-for-localhost-cli": "^3.0.0", + "zod": "^3.25.76" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -1117,13 +1144,8 @@ } }, "node_modules/@supabase/postgrest-js": { - "version": "1.19.4", - "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.19.4.tgz", - "integrity": "sha512-O4soKqKtZIW3olqmbXXbKugUtByD2jPa8kL2m2c1oozAO11uCcGrRhkZL0kVxjBLrXHE0mdSkFsMj7jDSfyNpw==", - "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "^2.6.14" - } + "resolved": "../postgrest-js", + "link": true }, "node_modules/@supabase/realtime-js": { "version": "2.15.1", diff --git a/package.json b/package.json index 9a801a41..a168a21a 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@supabase/auth-js": "2.71.1", "@supabase/functions-js": "2.4.5", "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "1.19.4", + "@supabase/postgrest-js": "file:../postgrest-js", "@supabase/realtime-js": "2.15.1", "@supabase/storage-js": "^2.10.4" }, diff --git a/src/SupabaseClient.ts b/src/SupabaseClient.ts index ca5733cd..b099f0ba 100644 --- a/src/SupabaseClient.ts +++ b/src/SupabaseClient.ts @@ -30,12 +30,32 @@ import { Fetch, GenericSchema, SupabaseClientOptions, SupabaseAuthClientOptions */ export default class SupabaseClient< Database = any, - SchemaName extends string & keyof Database = 'public' extends keyof Database + // The second type parameter is also used for specifying db_schema, so we + // support both cases. + // TODO: Allow setting db_schema from ClientOptions. + SchemaNameOrClientOptions extends + | (string & keyof Database) + | { PostgrestVersion: string } = 'public' extends keyof Database ? 'public' : string & keyof Database, - Schema extends GenericSchema = Database[SchemaName] extends GenericSchema - ? Database[SchemaName] - : any + SchemaName extends string & + keyof Omit = SchemaNameOrClientOptions extends string & + keyof Omit + ? SchemaNameOrClientOptions + : 'public' extends keyof Omit + ? 'public' + : string & keyof Omit, '__InternalSupabase'>, + Schema extends Omit[SchemaName] extends GenericSchema + ? Omit[SchemaName] + : never = Omit[SchemaName] extends GenericSchema + ? Omit[SchemaName] + : never, + ClientOptions extends { PostgrestVersion: string } = SchemaNameOrClientOptions extends string & + keyof Omit + ? { PostgrestVersion: '12' } + : SchemaNameOrClientOptions extends { PostgrestVersion: string } + ? SchemaNameOrClientOptions + : never > { /** * Supabase Auth allows you to create and manage user sessions for access to data that is secured by access policies. @@ -51,7 +71,7 @@ export default class SupabaseClient< protected authUrl: URL protected storageUrl: URL protected functionsUrl: URL - protected rest: PostgrestClient + protected rest: PostgrestClient protected storageKey: string protected fetch?: Fetch protected changedAccessToken?: string @@ -161,16 +181,16 @@ export default class SupabaseClient< from< TableName extends string & keyof Schema['Tables'], Table extends Schema['Tables'][TableName] - >(relation: TableName): PostgrestQueryBuilder + >(relation: TableName): PostgrestQueryBuilder from( relation: ViewName - ): PostgrestQueryBuilder + ): 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: string): PostgrestQueryBuilder { return this.rest.from(relation) } @@ -182,10 +202,11 @@ export default class SupabaseClient< * * @param schema - The schema to query */ - schema( + schema>( schema: DynamicSchema ): PostgrestClient< Database, + ClientOptions, DynamicSchema, Database[DynamicSchema] extends GenericSchema ? Database[DynamicSchema] : any > { @@ -225,6 +246,7 @@ export default class SupabaseClient< count?: 'exact' | 'planned' | 'estimated' } = {} ): PostgrestFilterBuilder< + ClientOptions, Schema, Fn['Returns'] extends any[] ? Fn['Returns'][number] extends Record @@ -233,7 +255,8 @@ export default class SupabaseClient< : never, Fn['Returns'], FnName, - null + null, + 'RPC' > { return this.rest.rpc(fn, args, options) } diff --git a/src/index.ts b/src/index.ts index 90d2b550..f071d8ee 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ import SupabaseClient from './SupabaseClient' -import type { GenericSchema, SupabaseClientOptions } from './lib/types' +import type { SupabaseClientOptions } from './lib/types' export * from '@supabase/auth-js' export type { User as AuthUser, Session as AuthSession } from '@supabase/auth-js' @@ -26,18 +26,28 @@ export type { SupabaseClientOptions, QueryResult, QueryData, QueryError } from ' */ export const createClient = < Database = any, - SchemaName extends string & keyof Database = 'public' extends keyof Database + SchemaNameOrClientOptions extends + | (string & keyof Database) + | { PostgrestVersion: string } = 'public' extends keyof Database ? 'public' : string & keyof Database, - Schema extends GenericSchema = Database[SchemaName] extends GenericSchema - ? Database[SchemaName] - : any + SchemaName extends string & + keyof Omit = SchemaNameOrClientOptions extends string & + keyof Omit + ? SchemaNameOrClientOptions + : 'public' extends keyof Omit + ? 'public' + : string & keyof Omit, '__InternalSupabase'> >( supabaseUrl: string, supabaseKey: string, options?: SupabaseClientOptions -): SupabaseClient => { - return new SupabaseClient(supabaseUrl, supabaseKey, options) +): SupabaseClient => { + return new SupabaseClient( + supabaseUrl, + supabaseKey, + options + ) } // Check for Node.js <= 18 deprecation diff --git a/test/types/index.test-d.ts b/test/types/index.test-d.ts index 0ae3fc35..6798a4fa 100644 --- a/test/types/index.test-d.ts +++ b/test/types/index.test-d.ts @@ -1,11 +1,17 @@ import { expectError, expectType } from 'tsd' -import { PostgrestSingleResponse, createClient } from '../../src/index' +import { PostgrestSingleResponse, createClient, SupabaseClient } from '../../src/index' import { Database, Json } from '../types' const URL = 'http://localhost:3000' const KEY = 'some.fake.key' const supabase = createClient(URL, KEY) +// createClient with custom schema +{ + createClient(URL, KEY, { db: { schema: 'personal' } }) + new SupabaseClient(URL, KEY, { db: { schema: 'personal' } }) +} + // table invalid type { expectError(supabase.from(42)) From 2ab66c052b773603026f26b61ca989bcdfc225c4 Mon Sep 17 00:00:00 2001 From: avallete Date: Thu, 21 Aug 2025 15:30:55 +0200 Subject: [PATCH 2/5] wip: restore tests --- package-lock.json | 38 +--- package.json | 2 +- test/integration/next/app/layout.tsx | 14 ++ test/integration/next/package.json | 4 +- .../next/tests/types/types.test-d.ts | 180 ++++++++++++++++++ test/integration/next/tsconfig.json | 2 +- test/types/index.test-d.ts | 122 +++++++++++- test/unit/SupabaseClient.test.ts | 18 +- 8 files changed, 332 insertions(+), 48 deletions(-) create mode 100644 test/integration/next/app/layout.tsx create mode 100644 test/integration/next/tests/types/types.test-d.ts diff --git a/package-lock.json b/package-lock.json index d5a69174..63b76823 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@supabase/auth-js": "2.71.1", "@supabase/functions-js": "2.4.5", "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "file:../postgrest-js", + "@supabase/postgrest-js": "https://pkg.pr.new/supabase/postgrest-js/@supabase/postgrest-js@78e9fcc", "@supabase/realtime-js": "2.15.1", "@supabase/storage-js": "^2.10.4" }, @@ -40,33 +40,6 @@ "webpack-cli": "^4.9.2" } }, - "../postgrest-js": { - "name": "@supabase/postgrest-js", - "version": "0.0.0-automated", - "license": "MIT", - "dependencies": { - "@supabase/node-fetch": "^2.6.14" - }, - "devDependencies": { - "@types/jest": "^27.5.1", - "chokidar-cli": "^3.0.0", - "cpy-cli": "^5.0.0", - "jest": "^28.1.0", - "node-abort-controller": "^3.0.1", - "npm-run-all": "^4.1.5", - "prettier": "^2.6.2", - "rimraf": "^3.0.2", - "semantic-release-plugin-update-version-in-files": "^1.1.0", - "ts-expect": "^1.3.0", - "ts-jest": "^28.0.3", - "tsd": "^0.31.2", - "type-fest": "^4.32.0", - "typedoc": "^0.22.16", - "typescript": "^4.5.5", - "wait-for-localhost-cli": "^3.0.0", - "zod": "^3.25.76" - } - }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -1144,8 +1117,13 @@ } }, "node_modules/@supabase/postgrest-js": { - "resolved": "../postgrest-js", - "link": true + "version": "0.0.0-automated", + "resolved": "https://pkg.pr.new/supabase/postgrest-js/@supabase/postgrest-js@78e9fcc", + "integrity": "sha512-uZ7sMcECsmLK/+om0s8PXl0NfTYulYG/ga8PYIDz/vssawd3bSPK88uR2fUEpz+qp3a6iN1fC94r4gHOahn5Zw==", + "license": "MIT", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } }, "node_modules/@supabase/realtime-js": { "version": "2.15.1", diff --git a/package.json b/package.json index a168a21a..816ba85a 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@supabase/auth-js": "2.71.1", "@supabase/functions-js": "2.4.5", "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "file:../postgrest-js", + "@supabase/postgrest-js": "https://pkg.pr.new/supabase/postgrest-js/@supabase/postgrest-js@78e9fcc", "@supabase/realtime-js": "2.15.1", "@supabase/storage-js": "^2.10.4" }, diff --git a/test/integration/next/app/layout.tsx b/test/integration/next/app/layout.tsx new file mode 100644 index 00000000..0cc4b8ea --- /dev/null +++ b/test/integration/next/app/layout.tsx @@ -0,0 +1,14 @@ +import type { Metadata } from 'next' + +export const metadata: Metadata = { + title: 'Supabase Integration Test', + description: 'Testing Supabase integration with Next.js', +} + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ) +} diff --git a/test/integration/next/package.json b/test/integration/next/package.json index 6ee2dc94..374cbda1 100644 --- a/test/integration/next/package.json +++ b/test/integration/next/package.json @@ -7,7 +7,8 @@ "lint": "next lint", "test": "playwright test", "test:ui": "playwright test --ui", - "test:debug": "playwright test --debug" + "test:debug": "playwright test --debug", + "test:types": "npx tsd --files tests/types/*.test-d.ts" }, "dependencies": { "@radix-ui/react-checkbox": "^1.3.1", @@ -37,6 +38,7 @@ "postcss": "^8", "tailwindcss": "^3.4.1", "tailwindcss-animate": "^1.0.7", + "tsd": "^0.33.0", "typescript": "^5" } } diff --git a/test/integration/next/tests/types/types.test-d.ts b/test/integration/next/tests/types/types.test-d.ts new file mode 100644 index 00000000..830d4f59 --- /dev/null +++ b/test/integration/next/tests/types/types.test-d.ts @@ -0,0 +1,180 @@ +import { createServerClient, createBrowserClient } from '@supabase/ssr' +import { expectType } from 'tsd' + +// Copied from ts-expect +// https://github.com/TypeStrong/ts-expect/blob/master/src/index.ts#L23-L27 +export type TypeEqual = (() => T extends Target ? 1 : 2) extends < + T +>() => T extends Value ? 1 : 2 + ? true + : false + +type Database = { + public: { + Tables: { + shops: { + Row: { + address: string | null + id: number + shop_geom: unknown | null + } + Insert: { + address?: string | null + id: number + shop_geom?: unknown | null + } + Update: { + address?: string | null + id?: number + shop_geom?: unknown | null + } + Relationships: [] + } + } + Views: { + [_ in never]: never + } + Functions: { + [_ in never]: never + } + Enums: { + [_ in never]: never + } + CompositeTypes: { + [_ in never]: never + } + } +} + +{ + // createBrowserClient should return a typed client + const pg12Client = createBrowserClient('HTTP://localhost:3000', '') + const res12 = await pg12Client.from('shops').select('*') + expectType< + TypeEqual< + | { + address: string | null + id: number + shop_geom: unknown | null + }[] + | null, + typeof res12.data + > + >(true) +} + +{ + // createBrowserClient should infer everything to any without types provided + const pg12Client = createBrowserClient('HTTP://localhost:3000', '') + const res12 = await pg12Client.from('shops').select('address, id, relation(field)') + expectType< + TypeEqual< + | { + address: any + id: any + relation: { + field: any + }[] + }[] + | null, + typeof res12.data + > + >(true) +} + +{ + // createServerClient should return a typed client + const pg12Server = createServerClient('HTTP://localhost:3000', '') + const res12 = await pg12Server.from('shops').select('*') + expectType< + TypeEqual< + | { + address: string | null + id: number + shop_geom: unknown | null + }[] + | null, + typeof res12.data + > + >(true) +} + +{ + // createServerClient should infer everything to any without types provided + const pg12Server = createServerClient('HTTP://localhost:3000', '') + const res12 = await pg12Server.from('shops').select('address, id, relation(field)') + expectType< + TypeEqual< + | { + address: any + id: any + relation: { + field: any + }[] + }[] + | null, + typeof res12.data + > + >(true) +} +// Should be able to get a PostgrestVersion 13 client from __InternalSupabase +{ + type DatabaseWithInternals = { + __InternalSupabase: { + PostgrestVersion: '13' + } + public: { + Tables: { + shops: { + Row: { + address: string | null + id: number + shop_geom: unknown | null + } + Insert: { + address?: string | null + id: number + shop_geom?: unknown | null + } + Update: { + address?: string | null + id?: number + shop_geom?: unknown | null + } + Relationships: [] + } + } + Views: { + [_ in never]: never + } + Functions: { + [_ in never]: never + } + Enums: { + [_ in never]: never + } + CompositeTypes: { + [_ in never]: never + } + } + } + const pg13BrowserClient = createBrowserClient('HTTP://localhost:3000', '') + const pg13ServerClient = createServerClient('HTTP://localhost:3000', '', { + cookies: { getAll: () => [], setAll: () => {} }, + }) + const res13 = await pg13BrowserClient.from('shops').update({ id: 21 }).maxAffected(1) + expectType(null) + const res13Server = await pg13ServerClient.from('shops').update({ id: 21 }).maxAffected(1) + expectType(null) +} +{ + // Should default to PostgrestVersion 12 + const pg12BrowserClient = createBrowserClient('HTTP://localhost:3000', '') + const pg12ServerClient = createServerClient('HTTP://localhost:3000', '', { + cookies: { getAll: () => [], setAll: () => {} }, + }) + const res12 = await pg12BrowserClient.from('shops').update({ id: 21 }).maxAffected(1) + expectType('maxAffected method only available on postgrest 13+') + const res12Server = await pg12ServerClient.from('shops').update({ id: 21 }).maxAffected(1) + expectType('maxAffected method only available on postgrest 13+') +} diff --git a/test/integration/next/tsconfig.json b/test/integration/next/tsconfig.json index ac0369a8..32d8de30 100644 --- a/test/integration/next/tsconfig.json +++ b/test/integration/next/tsconfig.json @@ -24,5 +24,5 @@ } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "exclude": ["node_modules", "test/types/*.test-d.ts"] } diff --git a/test/types/index.test-d.ts b/test/types/index.test-d.ts index 6798a4fa..57ef3ecc 100644 --- a/test/types/index.test-d.ts +++ b/test/types/index.test-d.ts @@ -1,17 +1,11 @@ import { expectError, expectType } from 'tsd' -import { PostgrestSingleResponse, createClient, SupabaseClient } from '../../src/index' +import { PostgrestSingleResponse, SupabaseClient, createClient } from '../../src/index' import { Database, Json } from '../types' const URL = 'http://localhost:3000' const KEY = 'some.fake.key' const supabase = createClient(URL, KEY) -// createClient with custom schema -{ - createClient(URL, KEY, { db: { schema: 'personal' } }) - new SupabaseClient(URL, KEY, { db: { schema: 'personal' } }) -} - // table invalid type { expectError(supabase.from(42)) @@ -142,3 +136,117 @@ const supabase = createClient(URL, KEY) }[] >(channels) } + +// Test Postgrest13 +// should be able to declare specific PostgrestVersion +{ + // @ts-expect-error should raise error if provinding invalid version + createClient('HTTP://localhost:3000', KEY) +} + +// should be able to infer PostgrestVersion from Database __InternalSupabase +{ + type DatabaseWithInternals = { + __InternalSupabase: { + PostgrestVersion: '13' + } + public: { + Tables: { + shops: { + Row: { + address: string | null + id: number + shop_geom: unknown | null + } + Insert: { + address?: string | null + id: number + shop_geom?: unknown | null + } + Update: { + address?: string | null + id?: number + shop_geom?: unknown | null + } + Relationships: [] + } + } + Views: { + [_ in never]: never + } + Functions: { + [_ in never]: never + } + Enums: { + [_ in never]: never + } + CompositeTypes: { + [_ in never]: never + } + } + } + // Note: The template argument properties (PostgrestVersion) will not be autocompleted + // due to a Typescript bug tracked here: https://github.com/microsoft/TypeScript/issues/56299 + const pg13Client = createClient('HTTP://localhost:3000', KEY) + const pg12Client = createClient('HTTP://localhost:3000', KEY) + const res13 = await pg13Client.from('shops').update({ id: 21 }).maxAffected(1) + const res12 = await pg12Client.from('shops').update({ id: 21 }).maxAffected(1) + expectType(null) + expectType('maxAffected method only available on postgrest 13+') +} + +// createClient with custom schema +{ + const pg12CustomSchemaClient = createClient(URL, KEY, { + db: { schema: 'personal' }, + }) + const pg12CustomSchemaNewClient = new SupabaseClient(URL, KEY, { + db: { schema: 'personal' }, + }) + const res12new = await pg12CustomSchemaNewClient + .from('users') + .update({ username: 'test' }) + .maxAffected(1) + const res12 = await pg12CustomSchemaClient + .from('users') + .update({ username: 'test' }) + .maxAffected(1) + expectType('maxAffected method only available on postgrest 13+') + expectType('maxAffected method only available on postgrest 13+') + // @ts-expect-error should raise error if providing table name not in the schema + pg12CustomSchemaClient.from('channels_details') + // @ts-expect-error should raise error if providing table name not in the schema + pg12CustomSchemaNewClient.from('channels_details') +} + +// createClient with custom schema and PostgrestVersion explicitly set +{ + const pg13CustomSchemaClient = createClient( + URL, + KEY, + { + db: { schema: 'personal' }, + } + ) + const pg12CustomSchemaNewClient = new SupabaseClient< + Database, + { PostgrestVersion: '12' }, + 'personal' + >(URL, KEY, { + db: { schema: 'personal' }, + }) + const res12new = await pg12CustomSchemaNewClient + .from('users') + .update({ username: 'test' }) + .maxAffected(1) + const res13 = await pg13CustomSchemaClient + .from('users') + .update({ username: 'test' }) + .maxAffected(1) + expectType(null) + expectType('maxAffected method only available on postgrest 13+') + // @ts-expect-error should raise error if providing table name not in the schema + pg12CustomSchemaClient.from('channels_details') + // @ts-expect-error should raise error if providing table name not in the schema + pg13CustomSchemaClient.from('channels_details') +} diff --git a/test/unit/SupabaseClient.test.ts b/test/unit/SupabaseClient.test.ts index 8e91f2da..81f420be 100644 --- a/test/unit/SupabaseClient.test.ts +++ b/test/unit/SupabaseClient.test.ts @@ -74,18 +74,20 @@ describe('SupabaseClient', () => { test('should have custom header set', () => { const customHeader = { 'X-Test-Header': 'value' } const request = createClient(URL, KEY, { global: { headers: customHeader } }).rpc('') - // @ts-ignore - const getHeaders = request.headers - expect(getHeaders).toHaveProperty('X-Test-Header', 'value') + //@ts-expect-error headers is protected attribute + const requestHeader = request.headers.get('X-Test-Header') + expect(requestHeader).toBe(customHeader['X-Test-Header']) }) test('should merge custom headers with default headers', () => { const customHeader = { 'X-Test-Header': 'value' } - const client = createClient(URL, KEY, { global: { headers: customHeader } }) - // @ts-ignore - expect(client.headers).toHaveProperty('X-Test-Header', 'value') - // @ts-ignore - expect(client.headers).toHaveProperty('X-Client-Info') + const request = createClient(URL, KEY, { global: { headers: customHeader } }).rpc('') + + //@ts-expect-error headers is protected attribute + const requestHeader = request.headers.get('X-Test-Header') + expect(requestHeader).toBe(customHeader['X-Test-Header']) + //@ts-expect-error headers is protected attribute + expect(request.headers.get('X-Client-Info')).not.toBeNull() }) }) From 7e9fbd6c5c205fed7e1780a9ac35689917023ffd Mon Sep 17 00:00:00 2001 From: avallete Date: Thu, 21 Aug 2025 15:34:17 +0200 Subject: [PATCH 3/5] wip: exclude __InternalSupabase --- src/SupabaseClient.ts | 6 +++--- src/index.ts | 6 +++--- test/types/index.test-d.ts | 4 ++++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/SupabaseClient.ts b/src/SupabaseClient.ts index b099f0ba..35fed941 100644 --- a/src/SupabaseClient.ts +++ b/src/SupabaseClient.ts @@ -34,10 +34,10 @@ export default class SupabaseClient< // support both cases. // TODO: Allow setting db_schema from ClientOptions. SchemaNameOrClientOptions extends - | (string & keyof Database) - | { PostgrestVersion: string } = 'public' extends keyof Database + | (string & keyof Omit) + | { PostgrestVersion: string } = 'public' extends keyof Omit ? 'public' - : string & keyof Database, + : string & keyof Omit, SchemaName extends string & keyof Omit = SchemaNameOrClientOptions extends string & keyof Omit diff --git a/src/index.ts b/src/index.ts index f071d8ee..95b97461 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,10 +27,10 @@ export type { SupabaseClientOptions, QueryResult, QueryData, QueryError } from ' export const createClient = < Database = any, SchemaNameOrClientOptions extends - | (string & keyof Database) - | { PostgrestVersion: string } = 'public' extends keyof Database + | (string & keyof Omit) + | { PostgrestVersion: string } = 'public' extends keyof Omit ? 'public' - : string & keyof Database, + : string & keyof Omit, SchemaName extends string & keyof Omit = SchemaNameOrClientOptions extends string & keyof Omit diff --git a/test/types/index.test-d.ts b/test/types/index.test-d.ts index 57ef3ecc..a8e92942 100644 --- a/test/types/index.test-d.ts +++ b/test/types/index.test-d.ts @@ -188,6 +188,10 @@ const supabase = createClient(URL, KEY) // Note: The template argument properties (PostgrestVersion) will not be autocompleted // due to a Typescript bug tracked here: https://github.com/microsoft/TypeScript/issues/56299 const pg13Client = createClient('HTTP://localhost:3000', KEY) + // @ts-expect-error should raise error if providing __InternalSupabase as schema name + createClient('HTTP://localhost:3000', KEY) + // @ts-expect-error should raise error if providing __InternalSupabase as schema name + new SupabaseClient('HTTP://localhost:3000', KEY) const pg12Client = createClient('HTTP://localhost:3000', KEY) const res13 = await pg13Client.from('shops').update({ id: 21 }).maxAffected(1) const res12 = await pg12Client.from('shops').update({ id: 21 }).maxAffected(1) From 8dea347e247da4d9bb722e2396b5888dcfcde551 Mon Sep 17 00:00:00 2001 From: avallete Date: Thu, 21 Aug 2025 16:04:04 +0200 Subject: [PATCH 4/5] feat: infer right version form __InternalSupabase --- src/SupabaseClient.ts | 6 +++++- test/types/index.test-d.ts | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/SupabaseClient.ts b/src/SupabaseClient.ts index 35fed941..1a0bb0ff 100644 --- a/src/SupabaseClient.ts +++ b/src/SupabaseClient.ts @@ -52,7 +52,11 @@ export default class SupabaseClient< : never, ClientOptions extends { PostgrestVersion: string } = SchemaNameOrClientOptions extends string & keyof Omit - ? { PostgrestVersion: '12' } + ? // If the version isn't explicitly set, look for it in the __InternalSupabase object to infer the right version + Database extends { __InternalSupabase: { PostgrestVersion: string } } + ? Database['__InternalSupabase'] + : // otherwise default to 12 + { PostgrestVersion: '12' } : SchemaNameOrClientOptions extends { PostgrestVersion: string } ? SchemaNameOrClientOptions : never diff --git a/test/types/index.test-d.ts b/test/types/index.test-d.ts index a8e92942..a95d6c00 100644 --- a/test/types/index.test-d.ts +++ b/test/types/index.test-d.ts @@ -195,8 +195,19 @@ const supabase = createClient(URL, KEY) const pg12Client = createClient('HTTP://localhost:3000', KEY) const res13 = await pg13Client.from('shops').update({ id: 21 }).maxAffected(1) const res12 = await pg12Client.from('shops').update({ id: 21 }).maxAffected(1) + const pg13ClientNew = new SupabaseClient('HTTP://localhost:3000', KEY) + const res13New = await pg13ClientNew.from('shops').update({ id: 21 }).maxAffected(1) expectType(null) + expectType(null) expectType('maxAffected method only available on postgrest 13+') + // Explicitly set PostgrestVersion should override the inferred __InternalSupabase schema version + const internal13Set12 = new SupabaseClient( + URL, + KEY + ) + const resinternal13Set12 = await internal13Set12.from('shops').update({ id: 21 }).maxAffected(1) + // The explicitly set PostgrestVersion should override the inferred __InternalSupabase schema version + expectType('maxAffected method only available on postgrest 13+') } // createClient with custom schema From d322819f7e08bf5c74df9a8eddeaafdd17245e3c Mon Sep 17 00:00:00 2001 From: Bobbie Soedirgo Date: Fri, 22 Aug 2025 03:15:09 +0800 Subject: [PATCH 5/5] chore: bump postgrest-js --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 63b76823..fdda4634 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@supabase/auth-js": "2.71.1", "@supabase/functions-js": "2.4.5", "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "https://pkg.pr.new/supabase/postgrest-js/@supabase/postgrest-js@78e9fcc", + "@supabase/postgrest-js": "1.21.3", "@supabase/realtime-js": "2.15.1", "@supabase/storage-js": "^2.10.4" }, @@ -1117,9 +1117,9 @@ } }, "node_modules/@supabase/postgrest-js": { - "version": "0.0.0-automated", - "resolved": "https://pkg.pr.new/supabase/postgrest-js/@supabase/postgrest-js@78e9fcc", - "integrity": "sha512-uZ7sMcECsmLK/+om0s8PXl0NfTYulYG/ga8PYIDz/vssawd3bSPK88uR2fUEpz+qp3a6iN1fC94r4gHOahn5Zw==", + "version": "1.21.3", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.21.3.tgz", + "integrity": "sha512-rg3DmmZQKEVCreXq6Am29hMVe1CzemXyIWVYyyua69y6XubfP+DzGfLxME/1uvdgwqdoaPbtjBDpEBhqxq1ZwA==", "license": "MIT", "dependencies": { "@supabase/node-fetch": "^2.6.14" diff --git a/package.json b/package.json index 816ba85a..d4bf3e22 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@supabase/auth-js": "2.71.1", "@supabase/functions-js": "2.4.5", "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "https://pkg.pr.new/supabase/postgrest-js/@supabase/postgrest-js@78e9fcc", + "@supabase/postgrest-js": "1.21.3", "@supabase/realtime-js": "2.15.1", "@supabase/storage-js": "^2.10.4" },