diff --git a/package-lock.json b/package-lock.json index b027d498..f08de6af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@supabase/auth-js": "2.70.0", "@supabase/functions-js": "2.4.5", "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "1.19.4", + "@supabase/postgrest-js": "1.21.0", "@supabase/realtime-js": "2.11.15", "@supabase/storage-js": "2.7.1" }, @@ -1101,9 +1101,9 @@ } }, "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==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.21.0.tgz", + "integrity": "sha512-fqpV5ZwaLVJyQnsmljJF6MnpRWnkjbLEymPylhVo9nFxr6XpkmP0XjRdsDwICBR2ugezoyPYj8yPCrPgSyys3Q==", "license": "MIT", "dependencies": { "@supabase/node-fetch": "^2.6.14" diff --git a/package.json b/package.json index 8bbecff7..69607f3e 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "@supabase/auth-js": "2.70.0", "@supabase/functions-js": "2.4.5", "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "1.19.4", + "@supabase/postgrest-js": "1.21.0", "@supabase/realtime-js": "2.11.15", "@supabase/storage-js": "2.7.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 13b3ffbc..ab3be54c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,14 +11,14 @@ importers: specifier: 2.70.0 version: 2.70.0 '@supabase/functions-js': - specifier: 2.4.4 - version: 2.4.4 + specifier: 2.4.5 + version: 2.4.5 '@supabase/node-fetch': specifier: 2.6.15 version: 2.6.15 '@supabase/postgrest-js': - specifier: 1.19.4 - version: 1.19.4 + specifier: 1.21.0 + version: 1.21.0 '@supabase/realtime-js': specifier: 2.11.15 version: 2.11.15 @@ -606,10 +606,10 @@ packages: integrity: sha512-BaAK/tOAZFJtzF1sE3gJ2FwTjLf4ky3PSvcvLGEgEmO4BSBkwWKu8l67rLLIBZPDnCyV7Owk2uPyKHa0kj5QGg==, } - '@supabase/functions-js@2.4.4': + '@supabase/functions-js@2.4.5': resolution: { - integrity: sha512-WL2p6r4AXNGwop7iwvul2BvOtuJ1YQy8EbOd0dhG1oN1q8el/BIRSFCFnWAMM/vJJlHWLi4ad22sKbKr9mvjoA==, + integrity: sha512-v5GSqb9zbosquTo6gBwIiq7W9eQ7rE5QazsK/ezNiQXdCbY+bH8D9qEaBIkhVvX4ZRW5rP03gEfw5yw9tiq4EQ==, } '@supabase/node-fetch@2.6.15': @@ -619,10 +619,10 @@ packages: } engines: { node: 4.x || >=6.0.0 } - '@supabase/postgrest-js@1.19.4': + '@supabase/postgrest-js@1.21.0': resolution: { - integrity: sha512-O4soKqKtZIW3olqmbXXbKugUtByD2jPa8kL2m2c1oozAO11uCcGrRhkZL0kVxjBLrXHE0mdSkFsMj7jDSfyNpw==, + integrity: sha512-fqpV5ZwaLVJyQnsmljJF6MnpRWnkjbLEymPylhVo9nFxr6XpkmP0XjRdsDwICBR2ugezoyPYj8yPCrPgSyys3Q==, } '@supabase/realtime-js@2.11.15': @@ -5594,7 +5594,7 @@ snapshots: dependencies: '@supabase/node-fetch': 2.6.15 - '@supabase/functions-js@2.4.4': + '@supabase/functions-js@2.4.5': dependencies: '@supabase/node-fetch': 2.6.15 @@ -5602,7 +5602,7 @@ snapshots: dependencies: whatwg-url: 5.0.0 - '@supabase/postgrest-js@1.19.4': + '@supabase/postgrest-js@1.21.0': dependencies: '@supabase/node-fetch': 2.6.15 diff --git a/src/SupabaseClient.ts b/src/SupabaseClient.ts index 50053eb9..93cb1600 100644 --- a/src/SupabaseClient.ts +++ b/src/SupabaseClient.ts @@ -4,6 +4,8 @@ import { PostgrestClient, PostgrestFilterBuilder, PostgrestQueryBuilder, + ClientServerOptions as PostgrestClientServerOption, + GetGenericDatabaseWithOptions, } from '@supabase/postgrest-js' import { RealtimeChannel, @@ -28,13 +30,18 @@ import { Fetch, GenericSchema, SupabaseClientOptions, SupabaseAuthClientOptions * * An isomorphic Javascript client for interacting with Postgres. */ + +export type ServicesOptions = PostgrestClientServerOption & {} + export default class SupabaseClient< Database = any, - SchemaName extends string & keyof Database = 'public' extends keyof Database + ClientOptions extends ServicesOptions = { PostgrestVersion: '12' }, + SchemaName extends string & + keyof GetGenericDatabaseWithOptions['db'] = 'public' extends keyof GetGenericDatabaseWithOptions['db'] ? 'public' - : string & keyof Database, - Schema extends GenericSchema = Database[SchemaName] extends GenericSchema - ? Database[SchemaName] + : string & keyof GetGenericDatabaseWithOptions['db'], + Schema extends GenericSchema = GetGenericDatabaseWithOptions['db'][SchemaName] extends GenericSchema + ? GetGenericDatabaseWithOptions['db'][SchemaName] : any > { /** @@ -47,7 +54,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 @@ -156,16 +163,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) } @@ -177,10 +184,11 @@ export default class SupabaseClient< * * @param schema - The schema to query */ - schema( + schema['db']>( schema: DynamicSchema ): PostgrestClient< Database, + ClientOptions, DynamicSchema, Database[DynamicSchema] extends GenericSchema ? Database[DynamicSchema] : any > { @@ -220,6 +228,7 @@ export default class SupabaseClient< count?: 'exact' | 'planned' | 'estimated' } = {} ): PostgrestFilterBuilder< + ClientOptions, Schema, Fn['Returns'] extends any[] ? Fn['Returns'][number] extends Record @@ -228,7 +237,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 ff601926..e3b104a6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,7 @@ import SupabaseClient from './SupabaseClient' import type { GenericSchema, SupabaseClientOptions } from './lib/types' +import type { ServicesOptions } from './SupabaseClient' +import type { GetGenericDatabaseWithOptions } from '@supabase/postgrest-js' export * from '@supabase/auth-js' export type { User as AuthUser, Session as AuthSession } from '@supabase/auth-js' @@ -26,16 +28,23 @@ export type { SupabaseClientOptions, QueryResult, QueryData, QueryError } from ' */ export const createClient = < Database = any, - SchemaName extends string & keyof Database = 'public' extends keyof Database + ClientOptions extends ServicesOptions = GetGenericDatabaseWithOptions['options'], + SchemaName extends string & + keyof GetGenericDatabaseWithOptions['db'] = 'public' extends keyof GetGenericDatabaseWithOptions['db'] ? 'public' - : string & keyof Database, - Schema extends GenericSchema = Database[SchemaName] extends GenericSchema - ? Database[SchemaName] + : string & keyof GetGenericDatabaseWithOptions['db'], + Schema = GetGenericDatabaseWithOptions['db'][SchemaName] extends GenericSchema + ? GetGenericDatabaseWithOptions['db'][SchemaName] : any >( supabaseUrl: string, supabaseKey: string, options?: SupabaseClientOptions -): SupabaseClient => { - return new SupabaseClient(supabaseUrl, supabaseKey, options) +) => { + return new SupabaseClient< + Database, + ClientOptions, + SchemaName, + Schema extends GenericSchema ? Schema : any + >(supabaseUrl, supabaseKey, options) } diff --git a/test/deno/integration.test.ts b/test/deno/integration.test.ts index ca06e275..9c50be6c 100644 --- a/test/deno/integration.test.ts +++ b/test/deno/integration.test.ts @@ -59,7 +59,7 @@ Deno.test( const { error: deleteError } = await supabase .from('todos') .delete() - .eq('id', createdTodo!.id) + .eq('id', createdTodo!.id as string) assertEquals(deleteError, null) @@ -67,7 +67,7 @@ Deno.test( const { data: fetchedTodo, error: fetchError } = await supabase .from('todos') .select('*') - .eq('id', createdTodo!.id) + .eq('id', createdTodo!.id as string) .single() assertExists(fetchError) diff --git a/test/deno/package-lock.json b/test/deno/package-lock.json index 640f9aef..49b64597 100644 --- a/test/deno/package-lock.json +++ b/test/deno/package-lock.json @@ -15,17 +15,17 @@ "license": "MIT", "dependencies": { "@supabase/auth-js": "2.70.0", - "@supabase/functions-js": "2.4.4", + "@supabase/functions-js": "2.4.5", "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "1.19.4", - "@supabase/realtime-js": "next", + "@supabase/postgrest-js": "1.21.0", + "@supabase/realtime-js": "2.11.15", "@supabase/storage-js": "2.7.1" }, "devDependencies": { "@sebbo2002/semantic-release-jsr": "^1.0.0", "@solana/wallet-standard-features": "^1.3.0", "@types/jest": "^29.2.5", - "husky": "^4.3.0", + "husky": "^4.3.8", "jest": "^29.3.1", "npm-run-all": "^4.1.5", "prettier": "^2.5.1", diff --git a/test/types/index.test-d.ts b/test/types/index.test-d.ts index 0ae3fc35..e71d5447 100644 --- a/test/types/index.test-d.ts +++ b/test/types/index.test-d.ts @@ -136,3 +136,59 @@ 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+') +} diff --git a/test/unit/SupabaseClient.test.ts b/test/unit/SupabaseClient.test.ts index 5e0783e5..be502cdd 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() }) })