1
1
import { FunctionsClient } from '@supabase/functions-js'
2
2
import { AuthChangeEvent } from '@supabase/gotrue-js'
3
- import { PostgrestClient , PostgrestQueryBuilder } from '@supabase/postgrest-js'
3
+ import {
4
+ PostgrestClient ,
5
+ PostgrestFilterBuilder ,
6
+ PostgrestQueryBuilder ,
7
+ } from '@supabase/postgrest-js'
4
8
import { RealtimeChannel , RealtimeClient , RealtimeClientOptions } from '@supabase/realtime-js'
5
9
import { SupabaseStorageClient } from '@supabase/storage-js'
6
10
import { DEFAULT_HEADERS , STORAGE_KEY } from './lib/constants'
7
11
import { fetchWithAuth } from './lib/fetch'
8
12
import { isBrowser , stripTrailingSlash } from './lib/helpers'
9
13
import { SupabaseAuthClient } from './lib/SupabaseAuthClient'
10
14
import { SupabaseRealtimeClient } from './lib/SupabaseRealtimeClient'
11
- import { Fetch , SupabaseClientOptions } from './lib/types'
15
+ import { Fetch , GenericSchema , SupabaseClientOptions } from './lib/types'
12
16
13
17
const DEFAULT_OPTIONS = {
14
18
schema : 'public' ,
@@ -24,19 +28,26 @@ const DEFAULT_OPTIONS = {
24
28
*
25
29
* An isomorphic Javascript client for interacting with Postgres.
26
30
*/
27
- export default class SupabaseClient {
31
+ export default class SupabaseClient <
32
+ Database = any ,
33
+ SchemaName extends string & keyof Database = 'public' extends keyof Database
34
+ ? 'public'
35
+ : string & keyof Database ,
36
+ Schema extends GenericSchema = Database [ SchemaName ] extends GenericSchema
37
+ ? Database [ SchemaName ]
38
+ : any
39
+ > {
28
40
/**
29
41
* Supabase Auth allows you to create and manage user sessions for access to data that is secured by access policies.
30
42
*/
31
43
auth : SupabaseAuthClient
32
44
33
- protected schema : string
34
- protected restUrl : string
35
45
protected realtimeUrl : string
36
46
protected authUrl : string
37
47
protected storageUrl : string
38
48
protected functionsUrl : string
39
49
protected realtime : RealtimeClient
50
+ protected rest : PostgrestClient < Database , SchemaName >
40
51
protected multiTab : boolean
41
52
protected fetch ?: Fetch
42
53
protected changedAccessToken : string | undefined
@@ -62,15 +73,14 @@ export default class SupabaseClient {
62
73
constructor (
63
74
protected supabaseUrl : string ,
64
75
protected supabaseKey : string ,
65
- options ?: SupabaseClientOptions
76
+ options ?: SupabaseClientOptions < SchemaName >
66
77
) {
67
78
if ( ! supabaseUrl ) throw new Error ( 'supabaseUrl is required.' )
68
79
if ( ! supabaseKey ) throw new Error ( 'supabaseKey is required.' )
69
80
70
81
const _supabaseUrl = stripTrailingSlash ( supabaseUrl )
71
82
const settings = { ...DEFAULT_OPTIONS , ...options }
72
83
73
- this . restUrl = `${ _supabaseUrl } /rest/v1`
74
84
this . realtimeUrl = `${ _supabaseUrl } /realtime/v1` . replace ( 'http' , 'ws' )
75
85
this . authUrl = `${ _supabaseUrl } /auth/v1`
76
86
this . storageUrl = `${ _supabaseUrl } /storage/v1`
@@ -83,15 +93,20 @@ export default class SupabaseClient {
83
93
this . functionsUrl = `${ _supabaseUrl } /functions/v1`
84
94
}
85
95
86
- this . schema = settings . schema
87
96
this . multiTab = settings . multiTab
88
97
this . headers = { ...DEFAULT_HEADERS , ...options ?. headers }
89
98
this . shouldThrowOnError = settings . shouldThrowOnError || false
90
99
100
+ this . fetch = fetchWithAuth ( supabaseKey , this . _getAccessToken . bind ( this ) , settings . fetch )
101
+
91
102
this . auth = this . _initSupabaseAuthClient ( settings )
92
103
this . realtime = this . _initRealtimeClient ( { headers : this . headers , ...settings . realtime } )
93
-
94
- this . fetch = fetchWithAuth ( supabaseKey , this . _getAccessToken . bind ( this ) , settings . fetch )
104
+ this . rest = new PostgrestClient ( `${ _supabaseUrl } /rest/v1` , {
105
+ headers : this . headers ,
106
+ schema : options ?. schema ,
107
+ fetch : this . fetch ,
108
+ throwOnError : this . shouldThrowOnError ,
109
+ } )
95
110
96
111
this . _listenForAuthEvents ( )
97
112
this . _listenForMultiTabEvents ( )
@@ -124,14 +139,11 @@ export default class SupabaseClient {
124
139
*
125
140
* @param table The table name to operate on.
126
141
*/
127
- from < T = any > ( table : string ) : PostgrestQueryBuilder < T > {
128
- const url = `${ this . restUrl } /${ table } `
129
- return new PostgrestQueryBuilder < T > ( url , {
130
- headers : this . headers ,
131
- schema : this . schema ,
132
- fetch : this . fetch ,
133
- shouldThrowOnError : this . shouldThrowOnError ,
134
- } )
142
+ from <
143
+ TableName extends string & keyof Schema [ 'Tables' ] ,
144
+ Table extends Schema [ 'Tables' ] [ TableName ]
145
+ > ( table : TableName ) : PostgrestQueryBuilder < Table > {
146
+ return this . rest . from ( table )
135
147
}
136
148
137
149
/**
@@ -143,16 +155,25 @@ export default class SupabaseClient {
143
155
* @param count Count algorithm to use to count rows in a table.
144
156
*
145
157
*/
146
- rpc < T = any > (
147
- fn : string ,
148
- params ?: object ,
149
- {
150
- head = false ,
151
- count = null ,
152
- } : { head ?: boolean ; count ?: null | 'exact' | 'planned' | 'estimated' } = { }
153
- ) {
154
- const rest = this . _initPostgRESTClient ( )
155
- return rest . rpc < T > ( fn , params , { head, count } )
158
+ rpc <
159
+ FunctionName extends string & keyof Schema [ 'Functions' ] ,
160
+ Function_ extends Schema [ 'Functions' ] [ FunctionName ]
161
+ > (
162
+ fn : FunctionName ,
163
+ args : Function_ [ 'Args' ] = { } ,
164
+ options ?: {
165
+ head ?: boolean
166
+ count ?: 'exact' | 'planned' | 'estimated'
167
+ }
168
+ ) : PostgrestFilterBuilder <
169
+ Function_ [ 'Returns' ] extends any [ ]
170
+ ? Function_ [ 'Returns' ] [ number ] extends Record < string , unknown >
171
+ ? Function_ [ 'Returns' ] [ number ]
172
+ : never
173
+ : never ,
174
+ Function_ [ 'Returns' ]
175
+ > {
176
+ return this . rest . rpc ( fn , args , options )
156
177
}
157
178
158
179
/**
@@ -249,7 +270,7 @@ export default class SupabaseClient {
249
270
fetch,
250
271
cookieOptions,
251
272
multiTab,
252
- } : SupabaseClientOptions ) {
273
+ } : SupabaseClientOptions < string > ) {
253
274
const authHeaders = {
254
275
Authorization : `Bearer ${ this . supabaseKey } ` ,
255
276
apikey : `${ this . supabaseKey } ` ,
@@ -274,15 +295,6 @@ export default class SupabaseClient {
274
295
} )
275
296
}
276
297
277
- private _initPostgRESTClient ( ) {
278
- return new PostgrestClient ( this . restUrl , {
279
- headers : this . headers ,
280
- schema : this . schema ,
281
- fetch : this . fetch ,
282
- throwOnError : this . shouldThrowOnError ,
283
- } )
284
- }
285
-
286
298
private _listenForMultiTabEvents ( ) {
287
299
if ( ! this . multiTab || ! isBrowser ( ) || ! window ?. addEventListener ) {
288
300
return null
0 commit comments