@supabase/gotrue-js 1.22.12 → 1.22.15
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/dist/main/GoTrueClient.d.ts +3 -8
- package/dist/main/GoTrueClient.d.ts.map +1 -1
- package/dist/main/GoTrueClient.js +47 -17
- package/dist/main/GoTrueClient.js.map +1 -1
- package/dist/main/lib/constants.d.ts +6 -1
- package/dist/main/lib/constants.d.ts.map +1 -1
- package/dist/main/lib/constants.js +7 -2
- package/dist/main/lib/constants.js.map +1 -1
- package/dist/main/lib/fetch.d.ts.map +1 -1
- package/dist/main/lib/fetch.js +4 -0
- package/dist/main/lib/fetch.js.map +1 -1
- package/dist/main/lib/helpers.d.ts +5 -0
- package/dist/main/lib/helpers.d.ts.map +1 -1
- package/dist/main/lib/helpers.js +44 -1
- package/dist/main/lib/helpers.js.map +1 -1
- package/dist/main/lib/types.d.ts +9 -0
- package/dist/main/lib/types.d.ts.map +1 -1
- package/dist/main/lib/version.d.ts +1 -1
- package/dist/main/lib/version.js +1 -1
- package/dist/module/GoTrueClient.d.ts +3 -8
- package/dist/module/GoTrueClient.d.ts.map +1 -1
- package/dist/module/GoTrueClient.js +49 -19
- package/dist/module/GoTrueClient.js.map +1 -1
- package/dist/module/lib/constants.d.ts +6 -1
- package/dist/module/lib/constants.d.ts.map +1 -1
- package/dist/module/lib/constants.js +6 -1
- package/dist/module/lib/constants.js.map +1 -1
- package/dist/module/lib/fetch.d.ts.map +1 -1
- package/dist/module/lib/fetch.js +4 -0
- package/dist/module/lib/fetch.js.map +1 -1
- package/dist/module/lib/helpers.d.ts +5 -0
- package/dist/module/lib/helpers.d.ts.map +1 -1
- package/dist/module/lib/helpers.js +39 -0
- package/dist/module/lib/helpers.js.map +1 -1
- package/dist/module/lib/types.d.ts +9 -0
- package/dist/module/lib/types.d.ts.map +1 -1
- package/dist/module/lib/version.d.ts +1 -1
- package/dist/module/lib/version.js +1 -1
- package/package.json +1 -1
- package/src/GoTrueClient.ts +70 -33
- package/src/lib/constants.ts +6 -1
- package/src/lib/fetch.ts +5 -0
- package/src/lib/helpers.ts +36 -0
- package/src/lib/types.ts +13 -0
- package/src/lib/version.ts +1 -1
package/src/GoTrueClient.ts
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import GoTrueApi from './GoTrueApi'
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
isBrowser,
|
|
4
|
+
getParameterByName,
|
|
5
|
+
uuid,
|
|
6
|
+
setItemAsync,
|
|
7
|
+
removeItemAsync,
|
|
8
|
+
getItemSynchronously,
|
|
9
|
+
getItemAsync,
|
|
10
|
+
} from './lib/helpers'
|
|
11
|
+
import {
|
|
12
|
+
GOTRUE_URL,
|
|
13
|
+
DEFAULT_HEADERS,
|
|
14
|
+
STORAGE_KEY,
|
|
15
|
+
EXPIRY_MARGIN,
|
|
16
|
+
NETWORK_FAILURE,
|
|
17
|
+
} from './lib/constants'
|
|
4
18
|
import { polyfillGlobalThis } from './lib/polyfills'
|
|
5
19
|
import { Fetch } from './lib/fetch'
|
|
6
20
|
|
|
@@ -16,6 +30,7 @@ import type {
|
|
|
16
30
|
UserCredentials,
|
|
17
31
|
VerifyOTPParams,
|
|
18
32
|
OpenIDConnectCredentials,
|
|
33
|
+
SupportedStorage,
|
|
19
34
|
} from './lib/types'
|
|
20
35
|
|
|
21
36
|
polyfillGlobalThis() // Make "globalThis" available
|
|
@@ -29,17 +44,6 @@ const DEFAULT_OPTIONS = {
|
|
|
29
44
|
headers: DEFAULT_HEADERS,
|
|
30
45
|
}
|
|
31
46
|
|
|
32
|
-
type AnyFunction = (...args: any[]) => any
|
|
33
|
-
type MaybePromisify<T> = T | Promise<T>
|
|
34
|
-
|
|
35
|
-
type PromisifyMethods<T> = {
|
|
36
|
-
[K in keyof T]: T[K] extends AnyFunction
|
|
37
|
-
? (...args: Parameters<T[K]>) => MaybePromisify<ReturnType<T[K]>>
|
|
38
|
-
: T[K]
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
type SupportedStorage = PromisifyMethods<Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>>
|
|
42
|
-
|
|
43
47
|
export default class GoTrueClient {
|
|
44
48
|
/**
|
|
45
49
|
* Namespace for the GoTrue API methods.
|
|
@@ -61,6 +65,7 @@ export default class GoTrueClient {
|
|
|
61
65
|
protected multiTab: boolean
|
|
62
66
|
protected stateChangeEmitters: Map<string, Subscription> = new Map()
|
|
63
67
|
protected refreshTokenTimer?: ReturnType<typeof setTimeout>
|
|
68
|
+
protected networkRetries: number = 0
|
|
64
69
|
|
|
65
70
|
/**
|
|
66
71
|
* Create a new client for use in the browser.
|
|
@@ -101,6 +106,7 @@ export default class GoTrueClient {
|
|
|
101
106
|
this._recoverSession()
|
|
102
107
|
this._recoverAndRefresh()
|
|
103
108
|
this._listenForMultiTabEvents()
|
|
109
|
+
this._handleVisibilityChange()
|
|
104
110
|
|
|
105
111
|
if (settings.detectSessionInUrl && isBrowser() && !!getParameterByName('access_token')) {
|
|
106
112
|
// Handle the OAuth redirect
|
|
@@ -407,6 +413,8 @@ export default class GoTrueClient {
|
|
|
407
413
|
user: this.user(),
|
|
408
414
|
}
|
|
409
415
|
|
|
416
|
+
this._notifyAllSubscribers('TOKEN_REFRESHED')
|
|
417
|
+
|
|
410
418
|
return this.currentSession
|
|
411
419
|
}
|
|
412
420
|
|
|
@@ -608,16 +616,12 @@ export default class GoTrueClient {
|
|
|
608
616
|
*/
|
|
609
617
|
private _recoverSession() {
|
|
610
618
|
try {
|
|
611
|
-
const
|
|
612
|
-
if (!
|
|
613
|
-
return null
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
const data = JSON.parse(json)
|
|
619
|
+
const data = getItemSynchronously(this.localStorage, STORAGE_KEY)
|
|
620
|
+
if (!data) return null
|
|
617
621
|
const { currentSession, expiresAt } = data
|
|
618
622
|
const timeNow = Math.round(Date.now() / 1000)
|
|
619
623
|
|
|
620
|
-
if (expiresAt >= timeNow && currentSession?.user) {
|
|
624
|
+
if (expiresAt >= timeNow + EXPIRY_MARGIN && currentSession?.user) {
|
|
621
625
|
this._saveSession(currentSession)
|
|
622
626
|
this._notifyAllSubscribers('SIGNED_IN')
|
|
623
627
|
}
|
|
@@ -632,22 +636,31 @@ export default class GoTrueClient {
|
|
|
632
636
|
*/
|
|
633
637
|
private async _recoverAndRefresh() {
|
|
634
638
|
try {
|
|
635
|
-
const
|
|
636
|
-
if (!
|
|
637
|
-
return null
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
const data = JSON.parse(json)
|
|
639
|
+
const data = await getItemAsync(this.localStorage, STORAGE_KEY)
|
|
640
|
+
if (!data) return null
|
|
641
641
|
const { currentSession, expiresAt } = data
|
|
642
642
|
const timeNow = Math.round(Date.now() / 1000)
|
|
643
643
|
|
|
644
|
-
if (expiresAt < timeNow) {
|
|
644
|
+
if (expiresAt < timeNow + EXPIRY_MARGIN) {
|
|
645
645
|
if (this.autoRefreshToken && currentSession.refresh_token) {
|
|
646
|
+
this.networkRetries++
|
|
646
647
|
const { error } = await this._callRefreshToken(currentSession.refresh_token)
|
|
647
648
|
if (error) {
|
|
648
649
|
console.log(error.message)
|
|
650
|
+
if (
|
|
651
|
+
error.message === NETWORK_FAILURE.ERROR_MESSAGE &&
|
|
652
|
+
this.networkRetries < NETWORK_FAILURE.MAX_RETRIES
|
|
653
|
+
) {
|
|
654
|
+
if (this.refreshTokenTimer) clearTimeout(this.refreshTokenTimer)
|
|
655
|
+
this.refreshTokenTimer = setTimeout(
|
|
656
|
+
() => this._recoverAndRefresh(),
|
|
657
|
+
NETWORK_FAILURE.RETRY_INTERVAL ** this.networkRetries * 100 // exponential backoff
|
|
658
|
+
)
|
|
659
|
+
return
|
|
660
|
+
}
|
|
649
661
|
await this._removeSession()
|
|
650
662
|
}
|
|
663
|
+
this.networkRetries = 0
|
|
651
664
|
} else {
|
|
652
665
|
this._removeSession()
|
|
653
666
|
}
|
|
@@ -701,7 +714,7 @@ export default class GoTrueClient {
|
|
|
701
714
|
if (expiresAt) {
|
|
702
715
|
const timeNow = Math.round(Date.now() / 1000)
|
|
703
716
|
const expiresIn = expiresAt - timeNow
|
|
704
|
-
const refreshDurationBeforeExpires = expiresIn >
|
|
717
|
+
const refreshDurationBeforeExpires = expiresIn > EXPIRY_MARGIN ? EXPIRY_MARGIN : 0.5
|
|
705
718
|
this._startAutoRefreshToken((expiresIn - refreshDurationBeforeExpires) * 1000)
|
|
706
719
|
}
|
|
707
720
|
|
|
@@ -714,14 +727,14 @@ export default class GoTrueClient {
|
|
|
714
727
|
|
|
715
728
|
private _persistSession(currentSession: Session) {
|
|
716
729
|
const data = { currentSession, expiresAt: currentSession.expires_at }
|
|
717
|
-
|
|
730
|
+
setItemAsync(this.localStorage, STORAGE_KEY, data)
|
|
718
731
|
}
|
|
719
732
|
|
|
720
733
|
private async _removeSession() {
|
|
721
734
|
this.currentSession = null
|
|
722
735
|
this.currentUser = null
|
|
723
736
|
if (this.refreshTokenTimer) clearTimeout(this.refreshTokenTimer)
|
|
724
|
-
|
|
737
|
+
removeItemAsync(this.localStorage, STORAGE_KEY)
|
|
725
738
|
}
|
|
726
739
|
|
|
727
740
|
/**
|
|
@@ -732,7 +745,16 @@ export default class GoTrueClient {
|
|
|
732
745
|
if (this.refreshTokenTimer) clearTimeout(this.refreshTokenTimer)
|
|
733
746
|
if (value <= 0 || !this.autoRefreshToken) return
|
|
734
747
|
|
|
735
|
-
this.refreshTokenTimer = setTimeout(() =>
|
|
748
|
+
this.refreshTokenTimer = setTimeout(async () => {
|
|
749
|
+
this.networkRetries++
|
|
750
|
+
const { error } = await this._callRefreshToken()
|
|
751
|
+
if (!error) this.networkRetries = 0
|
|
752
|
+
if (
|
|
753
|
+
error?.message === NETWORK_FAILURE.ERROR_MESSAGE &&
|
|
754
|
+
this.networkRetries < NETWORK_FAILURE.MAX_RETRIES
|
|
755
|
+
)
|
|
756
|
+
this._startAutoRefreshToken(NETWORK_FAILURE.RETRY_INTERVAL ** this.networkRetries * 100) // exponential backoff
|
|
757
|
+
}, value)
|
|
736
758
|
if (typeof this.refreshTokenTimer.unref === 'function') this.refreshTokenTimer.unref()
|
|
737
759
|
}
|
|
738
760
|
|
|
@@ -741,7 +763,6 @@ export default class GoTrueClient {
|
|
|
741
763
|
*/
|
|
742
764
|
private _listenForMultiTabEvents() {
|
|
743
765
|
if (!this.multiTab || !isBrowser() || !window?.addEventListener) {
|
|
744
|
-
// console.debug('Auth multi-tab support is disabled.')
|
|
745
766
|
return false
|
|
746
767
|
}
|
|
747
768
|
|
|
@@ -750,7 +771,7 @@ export default class GoTrueClient {
|
|
|
750
771
|
if (e.key === STORAGE_KEY) {
|
|
751
772
|
const newSession = JSON.parse(String(e.newValue))
|
|
752
773
|
if (newSession?.currentSession?.access_token) {
|
|
753
|
-
this.
|
|
774
|
+
this._saveSession(newSession.currentSession)
|
|
754
775
|
this._notifyAllSubscribers('SIGNED_IN')
|
|
755
776
|
} else {
|
|
756
777
|
this._removeSession()
|
|
@@ -762,4 +783,20 @@ export default class GoTrueClient {
|
|
|
762
783
|
console.error('_listenForMultiTabEvents', error)
|
|
763
784
|
}
|
|
764
785
|
}
|
|
786
|
+
|
|
787
|
+
private _handleVisibilityChange() {
|
|
788
|
+
if (!this.multiTab || !isBrowser() || !window?.addEventListener) {
|
|
789
|
+
return false
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
try {
|
|
793
|
+
window?.addEventListener('visibilitychange', () => {
|
|
794
|
+
if (document.visibilityState === 'visible') {
|
|
795
|
+
this._recoverAndRefresh()
|
|
796
|
+
}
|
|
797
|
+
})
|
|
798
|
+
} catch (error) {
|
|
799
|
+
console.error('_handleVisibilityChange', error)
|
|
800
|
+
}
|
|
801
|
+
}
|
|
765
802
|
}
|
package/src/lib/constants.ts
CHANGED
|
@@ -2,7 +2,12 @@ import { version } from './version'
|
|
|
2
2
|
export const GOTRUE_URL = 'http://localhost:9999'
|
|
3
3
|
export const AUDIENCE = ''
|
|
4
4
|
export const DEFAULT_HEADERS = { 'X-Client-Info': `gotrue-js/${version}` }
|
|
5
|
-
export const EXPIRY_MARGIN =
|
|
5
|
+
export const EXPIRY_MARGIN = 10 // in seconds
|
|
6
|
+
export const NETWORK_FAILURE = {
|
|
7
|
+
ERROR_MESSAGE: 'Request Failed',
|
|
8
|
+
MAX_RETRIES: 10,
|
|
9
|
+
RETRY_INTERVAL: 2, // in deciseconds
|
|
10
|
+
}
|
|
6
11
|
export const STORAGE_KEY = 'supabase.auth.token'
|
|
7
12
|
export const COOKIE_OPTIONS = {
|
|
8
13
|
name: 'sb',
|
package/src/lib/fetch.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { NETWORK_FAILURE } from './constants'
|
|
2
|
+
|
|
1
3
|
export type Fetch = typeof fetch
|
|
2
4
|
|
|
3
5
|
export interface FetchOptions {
|
|
@@ -13,6 +15,9 @@ const _getErrorMessage = (err: any): string =>
|
|
|
13
15
|
err.msg || err.message || err.error_description || err.error || JSON.stringify(err)
|
|
14
16
|
|
|
15
17
|
const handleError = (error: any, reject: any) => {
|
|
18
|
+
if (!error?.status) {
|
|
19
|
+
return reject({ message: NETWORK_FAILURE.ERROR_MESSAGE })
|
|
20
|
+
}
|
|
16
21
|
if (typeof error.json !== 'function') {
|
|
17
22
|
return reject(error)
|
|
18
23
|
}
|
package/src/lib/helpers.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import crossFetch from 'cross-fetch'
|
|
2
|
+
import { SupportedStorage } from './types'
|
|
2
3
|
|
|
3
4
|
export function expiresAt(expiresIn: number) {
|
|
4
5
|
const timeNow = Math.round(Date.now() / 1000)
|
|
@@ -39,3 +40,38 @@ export const resolveFetch = (customFetch?: Fetch): Fetch => {
|
|
|
39
40
|
}
|
|
40
41
|
return (...args) => _fetch(...args)
|
|
41
42
|
}
|
|
43
|
+
|
|
44
|
+
// LocalStorage helpers
|
|
45
|
+
export const setItemAsync = async (
|
|
46
|
+
storage: SupportedStorage,
|
|
47
|
+
key: string,
|
|
48
|
+
data: any
|
|
49
|
+
): Promise<void> => {
|
|
50
|
+
isBrowser() && (await storage?.setItem(key, JSON.stringify(data)))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const getItemAsync = async (storage: SupportedStorage, key: string): Promise<any | null> => {
|
|
54
|
+
const value = isBrowser() && (await storage?.getItem(key))
|
|
55
|
+
if (!value) return null
|
|
56
|
+
try {
|
|
57
|
+
return JSON.parse(value)
|
|
58
|
+
} catch {
|
|
59
|
+
return value
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const getItemSynchronously = (storage: SupportedStorage, key: string): any | null => {
|
|
64
|
+
const value = isBrowser() && storage?.getItem(key)
|
|
65
|
+
if (!value || typeof value !== 'string') {
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
return JSON.parse(value)
|
|
70
|
+
} catch {
|
|
71
|
+
return value
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const removeItemAsync = async (storage: SupportedStorage, key: string): Promise<void> => {
|
|
76
|
+
isBrowser() && (await storage?.removeItem(key))
|
|
77
|
+
}
|
package/src/lib/types.ts
CHANGED
|
@@ -69,6 +69,8 @@ export interface User {
|
|
|
69
69
|
aud: string
|
|
70
70
|
confirmation_sent_at?: string
|
|
71
71
|
recovery_sent_at?: string
|
|
72
|
+
email_change_sent_at?: string
|
|
73
|
+
new_email?: string
|
|
72
74
|
invited_at?: string
|
|
73
75
|
action_link?: string
|
|
74
76
|
email?: string
|
|
@@ -209,3 +211,14 @@ export interface OpenIDConnectCredentials {
|
|
|
209
211
|
client_id?: string
|
|
210
212
|
issuer?: string
|
|
211
213
|
}
|
|
214
|
+
|
|
215
|
+
type AnyFunction = (...args: any[]) => any
|
|
216
|
+
type MaybePromisify<T> = T | Promise<T>
|
|
217
|
+
|
|
218
|
+
type PromisifyMethods<T> = {
|
|
219
|
+
[K in keyof T]: T[K] extends AnyFunction
|
|
220
|
+
? (...args: Parameters<T[K]>) => MaybePromisify<ReturnType<T[K]>>
|
|
221
|
+
: T[K]
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export type SupportedStorage = PromisifyMethods<Pick<Storage, 'getItem' | 'setItem' | 'removeItem'>>
|
package/src/lib/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// generated by genversion
|
|
2
|
-
export const version = '1.22.
|
|
2
|
+
export const version = '1.22.15'
|