@supabase/supabase-js 1.28.2 → 1.28.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/main/SupabaseClient.d.ts +10 -0
- package/dist/main/SupabaseClient.d.ts.map +1 -1
- package/dist/main/SupabaseClient.js +75 -5
- package/dist/main/SupabaseClient.js.map +1 -1
- package/dist/main/lib/SupabaseQueryBuilder.d.ts +4 -1
- package/dist/main/lib/SupabaseQueryBuilder.d.ts.map +1 -1
- package/dist/main/lib/SupabaseQueryBuilder.js +8 -2
- package/dist/main/lib/SupabaseQueryBuilder.js.map +1 -1
- package/dist/main/lib/constants.d.ts +1 -0
- package/dist/main/lib/constants.d.ts.map +1 -1
- package/dist/main/lib/constants.js +2 -1
- package/dist/main/lib/constants.js.map +1 -1
- package/dist/main/lib/helpers.d.ts +1 -0
- package/dist/main/lib/helpers.d.ts.map +1 -1
- package/dist/main/lib/helpers.js +3 -1
- package/dist/main/lib/helpers.js.map +1 -1
- package/dist/main/lib/version.d.ts +1 -1
- package/dist/main/lib/version.js +1 -1
- package/dist/module/SupabaseClient.d.ts +10 -0
- package/dist/module/SupabaseClient.d.ts.map +1 -1
- package/dist/module/SupabaseClient.js +76 -6
- package/dist/module/SupabaseClient.js.map +1 -1
- package/dist/module/lib/SupabaseQueryBuilder.d.ts +4 -1
- package/dist/module/lib/SupabaseQueryBuilder.d.ts.map +1 -1
- package/dist/module/lib/SupabaseQueryBuilder.js +8 -2
- package/dist/module/lib/SupabaseQueryBuilder.js.map +1 -1
- package/dist/module/lib/constants.d.ts +1 -0
- package/dist/module/lib/constants.d.ts.map +1 -1
- package/dist/module/lib/constants.js +1 -0
- package/dist/module/lib/constants.js.map +1 -1
- package/dist/module/lib/helpers.d.ts +1 -0
- package/dist/module/lib/helpers.d.ts.map +1 -1
- package/dist/module/lib/helpers.js +1 -0
- package/dist/module/lib/helpers.js.map +1 -1
- package/dist/module/lib/version.d.ts +1 -1
- package/dist/module/lib/version.js +1 -1
- package/dist/umd/supabase.js +1 -1
- package/package.json +4 -3
- package/src/SupabaseClient.ts +86 -6
- package/src/lib/SupabaseQueryBuilder.ts +16 -3
- package/src/lib/constants.ts +1 -0
- package/src/lib/helpers.ts +2 -0
- package/src/lib/version.ts +1 -1
package/src/SupabaseClient.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { DEFAULT_HEADERS } from './lib/constants'
|
|
2
|
-
import { stripTrailingSlash } from './lib/helpers'
|
|
1
|
+
import { DEFAULT_HEADERS, STORAGE_KEY } from './lib/constants'
|
|
2
|
+
import { stripTrailingSlash, isBrowser } from './lib/helpers'
|
|
3
3
|
import { Fetch, SupabaseClientOptions } from './lib/types'
|
|
4
4
|
import { SupabaseAuthClient } from './lib/SupabaseAuthClient'
|
|
5
5
|
import { SupabaseQueryBuilder } from './lib/SupabaseQueryBuilder'
|
|
6
6
|
import { SupabaseStorageClient } from '@supabase/storage-js'
|
|
7
7
|
import { PostgrestClient } from '@supabase/postgrest-js'
|
|
8
|
+
import { AuthChangeEvent, Session, Subscription } from '@supabase/gotrue-js'
|
|
8
9
|
import { RealtimeClient, RealtimeSubscription, RealtimeClientOptions } from '@supabase/realtime-js'
|
|
9
10
|
|
|
10
11
|
const DEFAULT_OPTIONS = {
|
|
@@ -12,6 +13,7 @@ const DEFAULT_OPTIONS = {
|
|
|
12
13
|
autoRefreshToken: true,
|
|
13
14
|
persistSession: true,
|
|
14
15
|
detectSessionInUrl: true,
|
|
16
|
+
multiTab: true,
|
|
15
17
|
headers: DEFAULT_HEADERS,
|
|
16
18
|
}
|
|
17
19
|
|
|
@@ -32,7 +34,9 @@ export default class SupabaseClient {
|
|
|
32
34
|
protected authUrl: string
|
|
33
35
|
protected storageUrl: string
|
|
34
36
|
protected realtime: RealtimeClient
|
|
37
|
+
protected multiTab: boolean
|
|
35
38
|
protected fetch?: Fetch
|
|
39
|
+
protected changedAccessToken: string | undefined
|
|
36
40
|
protected headers: {
|
|
37
41
|
[key: string]: string
|
|
38
42
|
}
|
|
@@ -47,6 +51,7 @@ export default class SupabaseClient {
|
|
|
47
51
|
* @param options.detectSessionInUrl Set to "true" if you want to automatically detects OAuth grants in the URL and signs in the user.
|
|
48
52
|
* @param options.headers Any additional headers to send with each network request.
|
|
49
53
|
* @param options.realtime Options passed along to realtime-js constructor.
|
|
54
|
+
* @param options.multiTab Set to "false" if you want to disable multi-tab/window events.
|
|
50
55
|
* @param options.fetch A custom fetch implementation.
|
|
51
56
|
*/
|
|
52
57
|
constructor(
|
|
@@ -65,12 +70,16 @@ export default class SupabaseClient {
|
|
|
65
70
|
this.authUrl = `${supabaseUrl}/auth/v1`
|
|
66
71
|
this.storageUrl = `${supabaseUrl}/storage/v1`
|
|
67
72
|
this.schema = settings.schema
|
|
73
|
+
this.multiTab = settings.multiTab
|
|
68
74
|
this.fetch = settings.fetch
|
|
69
75
|
this.headers = { ...DEFAULT_HEADERS, ...options?.headers }
|
|
70
76
|
|
|
71
77
|
this.auth = this._initSupabaseAuthClient(settings)
|
|
72
78
|
this.realtime = this._initRealtimeClient({ headers: this.headers, ...settings.realtime })
|
|
73
79
|
|
|
80
|
+
this._listenForAuthEvents()
|
|
81
|
+
this._listenForMultiTabEvents()
|
|
82
|
+
|
|
74
83
|
// In the future we might allow the user to pass in a logger to receive these events.
|
|
75
84
|
// this.realtime.onOpen(() => console.log('OPEN'))
|
|
76
85
|
// this.realtime.onClose(() => console.log('CLOSED'))
|
|
@@ -121,6 +130,14 @@ export default class SupabaseClient {
|
|
|
121
130
|
return rest.rpc<T>(fn, params, { head, count })
|
|
122
131
|
}
|
|
123
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Remove all subscriptions.
|
|
135
|
+
*/
|
|
136
|
+
async removeAllSubscriptions() {
|
|
137
|
+
const subscriptions = this.realtime.channels.slice()
|
|
138
|
+
return await Promise.allSettled(subscriptions.map((sub) => this.removeSubscription(sub)))
|
|
139
|
+
}
|
|
140
|
+
|
|
124
141
|
/**
|
|
125
142
|
* Removes an active subscription and returns the number of open connections.
|
|
126
143
|
*
|
|
@@ -131,12 +148,14 @@ export default class SupabaseClient {
|
|
|
131
148
|
try {
|
|
132
149
|
await this._closeSubscription(subscription)
|
|
133
150
|
|
|
134
|
-
const
|
|
135
|
-
|
|
151
|
+
const allSubscriptions = this.getSubscriptions()
|
|
152
|
+
const openSubscriptionsCount = allSubscriptions.filter((chan) => chan.isJoined()).length
|
|
153
|
+
|
|
154
|
+
if (!allSubscriptions.length) {
|
|
136
155
|
const { error } = await this.realtime.disconnect()
|
|
137
156
|
if (error) return resolve({ error })
|
|
138
157
|
}
|
|
139
|
-
return resolve({ error: null, data: { openSubscriptions } })
|
|
158
|
+
return resolve({ error: null, data: { openSubscriptions: openSubscriptionsCount } })
|
|
140
159
|
} catch (error) {
|
|
141
160
|
return resolve({ error })
|
|
142
161
|
}
|
|
@@ -147,6 +166,11 @@ export default class SupabaseClient {
|
|
|
147
166
|
if (!subscription.isClosed()) {
|
|
148
167
|
await this._closeChannel(subscription)
|
|
149
168
|
}
|
|
169
|
+
|
|
170
|
+
return new Promise((resolve) => {
|
|
171
|
+
this.realtime.remove(subscription)
|
|
172
|
+
return resolve(true)
|
|
173
|
+
})
|
|
150
174
|
}
|
|
151
175
|
|
|
152
176
|
/**
|
|
@@ -207,10 +231,66 @@ export default class SupabaseClient {
|
|
|
207
231
|
subscription
|
|
208
232
|
.unsubscribe()
|
|
209
233
|
.receive('ok', () => {
|
|
210
|
-
this.realtime.remove(subscription)
|
|
211
234
|
return resolve(true)
|
|
212
235
|
})
|
|
213
236
|
.receive('error', (e: Error) => reject(e))
|
|
214
237
|
})
|
|
215
238
|
}
|
|
239
|
+
|
|
240
|
+
private _listenForMultiTabEvents() {
|
|
241
|
+
if (!this.multiTab || !isBrowser() || !window?.addEventListener) {
|
|
242
|
+
return null
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
return window?.addEventListener('storage', (e: StorageEvent) => {
|
|
247
|
+
if (e.key === STORAGE_KEY) {
|
|
248
|
+
const newSession = JSON.parse(String(e.newValue))
|
|
249
|
+
const accessToken: string | undefined =
|
|
250
|
+
newSession?.currentSession?.access_token ?? undefined
|
|
251
|
+
const previousAccessToken = this.auth.session()?.access_token
|
|
252
|
+
if (!accessToken) {
|
|
253
|
+
this._handleTokenChanged('SIGNED_OUT', accessToken, 'STORAGE')
|
|
254
|
+
} else if (!previousAccessToken && accessToken) {
|
|
255
|
+
this._handleTokenChanged('SIGNED_IN', accessToken, 'STORAGE')
|
|
256
|
+
} else if (previousAccessToken !== accessToken) {
|
|
257
|
+
this._handleTokenChanged('TOKEN_REFRESHED', accessToken, 'STORAGE')
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
})
|
|
261
|
+
} catch (error) {
|
|
262
|
+
console.error('_listenForMultiTabEvents', error)
|
|
263
|
+
return null
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
private _listenForAuthEvents() {
|
|
268
|
+
let { data } = this.auth.onAuthStateChange((event, session) => {
|
|
269
|
+
this._handleTokenChanged(event, session?.access_token, 'CLIENT')
|
|
270
|
+
})
|
|
271
|
+
return data
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
private _handleTokenChanged(
|
|
275
|
+
event: AuthChangeEvent,
|
|
276
|
+
token: string | undefined,
|
|
277
|
+
source: 'CLIENT' | 'STORAGE'
|
|
278
|
+
) {
|
|
279
|
+
if (
|
|
280
|
+
(event === 'TOKEN_REFRESHED' || event === 'SIGNED_IN') &&
|
|
281
|
+
this.changedAccessToken !== token
|
|
282
|
+
) {
|
|
283
|
+
// Token has changed
|
|
284
|
+
this.realtime.setAuth(token!)
|
|
285
|
+
// Ideally we should call this.auth.recoverSession() - need to make public
|
|
286
|
+
// to trigger a "SIGNED_IN" event on this client.
|
|
287
|
+
if (source == 'STORAGE') this.auth.setAuth(token!)
|
|
288
|
+
|
|
289
|
+
this.changedAccessToken = token
|
|
290
|
+
} else if (event === 'SIGNED_OUT' || event === 'USER_DELETED') {
|
|
291
|
+
// Token is removed
|
|
292
|
+
this.removeAllSubscriptions()
|
|
293
|
+
if (source == 'STORAGE') this.auth.signOut()
|
|
294
|
+
}
|
|
295
|
+
}
|
|
216
296
|
}
|
|
@@ -4,8 +4,11 @@ import { RealtimeClient } from '@supabase/realtime-js'
|
|
|
4
4
|
import { Fetch, SupabaseEventTypes, SupabaseRealtimePayload } from './types'
|
|
5
5
|
|
|
6
6
|
export class SupabaseQueryBuilder<T> extends PostgrestQueryBuilder<T> {
|
|
7
|
-
private _subscription: SupabaseRealtimeClient
|
|
7
|
+
private _subscription: SupabaseRealtimeClient | null = null
|
|
8
8
|
private _realtime: RealtimeClient
|
|
9
|
+
private _headers: { [key: string]: string }
|
|
10
|
+
private _schema: string
|
|
11
|
+
private _table: string
|
|
9
12
|
|
|
10
13
|
constructor(
|
|
11
14
|
url: string,
|
|
@@ -25,12 +28,14 @@ export class SupabaseQueryBuilder<T> extends PostgrestQueryBuilder<T> {
|
|
|
25
28
|
) {
|
|
26
29
|
super(url, { headers, schema, fetch })
|
|
27
30
|
|
|
28
|
-
this._subscription = new SupabaseRealtimeClient(realtime, headers, schema, table)
|
|
29
31
|
this._realtime = realtime
|
|
32
|
+
this._headers = headers
|
|
33
|
+
this._schema = schema
|
|
34
|
+
this._table = table
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
/**
|
|
33
|
-
* Subscribe to realtime changes in your
|
|
38
|
+
* Subscribe to realtime changes in your database.
|
|
34
39
|
* @param event The database event which you would like to receive updates for, or you can use the special wildcard `*` to listen to all changes.
|
|
35
40
|
* @param callback A callback that will handle the payload that is sent whenever your database changes.
|
|
36
41
|
*/
|
|
@@ -41,6 +46,14 @@ export class SupabaseQueryBuilder<T> extends PostgrestQueryBuilder<T> {
|
|
|
41
46
|
if (!this._realtime.isConnected()) {
|
|
42
47
|
this._realtime.connect()
|
|
43
48
|
}
|
|
49
|
+
if (!this._subscription) {
|
|
50
|
+
this._subscription = new SupabaseRealtimeClient(
|
|
51
|
+
this._realtime,
|
|
52
|
+
this._headers,
|
|
53
|
+
this._schema,
|
|
54
|
+
this._table
|
|
55
|
+
)
|
|
56
|
+
}
|
|
44
57
|
return this._subscription.on(event, callback)
|
|
45
58
|
}
|
|
46
59
|
}
|
package/src/lib/constants.ts
CHANGED
package/src/lib/helpers.ts
CHANGED
package/src/lib/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// generated by genversion
|
|
2
|
-
export const version = '1.28.
|
|
2
|
+
export const version = '1.28.6'
|