@@ -14,9 +14,11 @@ import 'package:jwt_decode/jwt_decode.dart';
14
14
import 'package:meta/meta.dart' ;
15
15
import 'package:retry/retry.dart' ;
16
16
import 'package:rxdart/subjects.dart' ;
17
+ import 'package:logging/logging.dart' ;
17
18
18
19
import 'broadcast_stub.dart' if (dart.library.html) './broadcast_web.dart'
19
20
as web;
21
+ import 'version.dart' ;
20
22
21
23
part 'gotrue_mfa_api.dart' ;
22
24
@@ -87,6 +89,8 @@ class GoTrueClient {
87
89
88
90
final AuthFlowType _flowType;
89
91
92
+ final _log = Logger ('supabase.gotrue' );
93
+
90
94
/// Proxy to the web BroadcastChannel API. Should be null on non-web platforms.
91
95
BroadcastChannel ? _broadcastChannel;
92
96
@@ -101,20 +105,22 @@ class GoTrueClient {
101
105
GotrueAsyncStorage ? asyncStorage,
102
106
AuthFlowType flowType = AuthFlowType .pkce,
103
107
}) : _url = url ?? Constants .defaultGotrueUrl,
104
- _headers = headers ?? {},
108
+ _headers = {
109
+ ...Constants .defaultHeaders,
110
+ ...? headers,
111
+ },
105
112
_httpClient = httpClient,
106
113
_asyncStorage = asyncStorage,
107
114
_flowType = flowType {
108
115
_autoRefreshToken = autoRefreshToken ?? true ;
109
116
110
117
final gotrueUrl = url ?? Constants .defaultGotrueUrl;
111
- final gotrueHeader = {
112
- ...Constants .defaultHeaders,
113
- if (headers != null ) ...headers,
114
- };
118
+ _log.config (
119
+ 'Initialize GoTrueClient v$version with url: $_url , autoRefreshToken: $_autoRefreshToken , flowType: $_flowType , tickDuration: ${Constants .autoRefreshTickDuration }, tickThreshold: ${Constants .autoRefreshTickThreshold }' );
120
+ _log.finest ('Initialize with headers: $_headers ' );
115
121
admin = GoTrueAdminApi (
116
122
gotrueUrl,
117
- headers: gotrueHeader ,
123
+ headers: _headers ,
118
124
httpClient: httpClient,
119
125
);
120
126
mfa = GoTrueMFAApi (
@@ -617,8 +623,10 @@ class GoTrueClient {
617
623
/// If the current session's refresh token is invalid, an error will be thrown.
618
624
Future <AuthResponse > refreshSession ([String ? refreshToken]) async {
619
625
if (currentSession? .accessToken == null ) {
626
+ _log.warning ("Can't refresh session, no current session found." );
620
627
throw AuthSessionMissingException ();
621
628
}
629
+ _log.info ('Refresh session' );
622
630
623
631
final currentSessionRefreshToken =
624
632
refreshToken ?? _currentSession? .refreshToken;
@@ -842,6 +850,7 @@ class GoTrueClient {
842
850
Future <void > signOut ({
843
851
SignOutScope scope = SignOutScope .local,
844
852
}) async {
853
+ _log.info ('Signing out user with scope: $scope ' );
845
854
final accessToken = currentSession? .accessToken;
846
855
847
856
if (scope != SignOutScope .others) {
@@ -966,13 +975,15 @@ class GoTrueClient {
966
975
try {
967
976
final session = Session .fromJson (json.decode (jsonStr));
968
977
if (session == null ) {
978
+ _log.warning ("Can't recover session from string, session is null" );
969
979
await signOut ();
970
980
throw notifyException (
971
981
AuthException ('Current session is missing data.' ),
972
982
);
973
983
}
974
984
975
985
if (session.isExpired) {
986
+ _log.fine ('Session from recovery is expired' );
976
987
final refreshToken = session.refreshToken;
977
988
if (_autoRefreshToken && refreshToken != null ) {
978
989
return await _callRefreshToken (refreshToken);
@@ -1002,6 +1013,7 @@ class GoTrueClient {
1002
1013
void startAutoRefresh () async {
1003
1014
stopAutoRefresh ();
1004
1015
1016
+ _log.fine ('Starting auto refresh' );
1005
1017
_autoRefreshTicker = Timer .periodic (
1006
1018
Constants .autoRefreshTickDuration,
1007
1019
(Timer t) => _autoRefreshTokenTick (),
@@ -1013,6 +1025,7 @@ class GoTrueClient {
1013
1025
1014
1026
/// Stops an active auto refresh process running in the background (if any).
1015
1027
void stopAutoRefresh () {
1028
+ _log.fine ('Stopping auto refresh' );
1016
1029
_autoRefreshTicker? .cancel ();
1017
1030
_autoRefreshTicker = null ;
1018
1031
}
@@ -1037,12 +1050,15 @@ class GoTrueClient {
1037
1050
Constants .autoRefreshTickDuration.inMilliseconds)
1038
1051
.floor ();
1039
1052
1053
+ _log.finer ('Access token expires in $expiresInTicks ticks' );
1054
+
1040
1055
// Only tick if the next tick comes after the retry threshold
1041
1056
if (expiresInTicks <= Constants .autoRefreshTickThreshold) {
1042
1057
await _callRefreshToken (refreshToken);
1043
1058
}
1044
1059
} catch (error) {
1045
- // Do nothing. JS client prints here
1060
+ // Do nothing. JS client prints here, but error is already tracked via
1061
+ // [notifyException]
1046
1062
}
1047
1063
}
1048
1064
@@ -1055,6 +1071,7 @@ class GoTrueClient {
1055
1071
// Make a GET request
1056
1072
() async {
1057
1073
attempt++ ;
1074
+ _log.fine ('Attempt $attempt to refresh token' );
1058
1075
final options = GotrueRequestOptions (
1059
1076
headers: _headers,
1060
1077
body: {'refresh_token' : refreshToken},
@@ -1129,11 +1146,14 @@ class GoTrueClient {
1129
1146
1130
1147
/// set currentSession and currentUser
1131
1148
void _saveSession (Session session) {
1149
+ _log.finest ('Saving session: $session ' );
1150
+ _log.fine ('Saving session' );
1132
1151
_currentSession = session;
1133
1152
_currentUser = session.user;
1134
1153
}
1135
1154
1136
1155
void _removeSession () {
1156
+ _log.fine ('Removing session' );
1137
1157
_currentSession = null ;
1138
1158
_currentUser = null ;
1139
1159
}
@@ -1151,6 +1171,8 @@ class GoTrueClient {
1151
1171
_broadcastChannelSubscription =
1152
1172
_broadcastChannel? .onMessage.listen ((messageEvent) {
1153
1173
final rawEvent = messageEvent['event' ];
1174
+ _log.finest ('Received broadcast message: $messageEvent ' );
1175
+ _log.info ('Received broadcast event: $rawEvent ' );
1154
1176
final event = switch (rawEvent) {
1155
1177
// This library sends the js name of the event to be comptabile with
1156
1178
// the js library, so we need to convert it back to the dart name
@@ -1202,6 +1224,7 @@ class GoTrueClient {
1202
1224
Future <AuthResponse > _callRefreshToken (String refreshToken) async {
1203
1225
// Refreshing is already in progress
1204
1226
if (_refreshTokenCompleter != null ) {
1227
+ _log.finer ("Don't call refresh token, already in progress" );
1205
1228
return _refreshTokenCompleter! .future;
1206
1229
}
1207
1230
@@ -1213,6 +1236,7 @@ class GoTrueClient {
1213
1236
(_) => null ,
1214
1237
onError: (_, __) => null ,
1215
1238
);
1239
+ _log.fine ('Refresh access token' );
1216
1240
1217
1241
final data = await _refreshAccessToken (refreshToken);
1218
1242
@@ -1232,15 +1256,15 @@ class GoTrueClient {
1232
1256
_removeSession ();
1233
1257
notifyAllSubscribers (AuthChangeEvent .signedOut);
1234
1258
} else {
1235
- _onAuthStateChangeController. addError (error, stack);
1259
+ notifyException (error, stack);
1236
1260
}
1237
1261
1238
1262
_refreshTokenCompleter? .completeError (error);
1239
1263
1240
1264
rethrow ;
1241
1265
} catch (error, stack) {
1242
1266
_refreshTokenCompleter? .completeError (error);
1243
- _onAuthStateChangeController. addError (error, stack);
1267
+ notifyException (error, stack);
1244
1268
rethrow ;
1245
1269
} finally {
1246
1270
_refreshTokenCompleter = null ;
@@ -1265,13 +1289,15 @@ class GoTrueClient {
1265
1289
});
1266
1290
}
1267
1291
final state = AuthState (event, session, fromBroadcast: ! broadcast);
1292
+ _log.finest ('onAuthStateChange: $state ' );
1268
1293
_onAuthStateChangeController.add (state);
1269
1294
_onAuthStateChangeControllerSync.add (state);
1270
1295
}
1271
1296
1272
1297
/// For internal use only.
1273
1298
@internal
1274
1299
Object notifyException (Object exception, [StackTrace ? stackTrace]) {
1300
+ _log.warning ('Notifying exception' , exception, stackTrace);
1275
1301
_onAuthStateChangeController.addError (
1276
1302
exception,
1277
1303
stackTrace ?? StackTrace .current,
0 commit comments