connect method
Implementation
Future<void> connect() async {
if (_state is! Disconnected) {
SdkLogger.i('Already connected or connecting');
return;
}
_shouldReconnect = true;
_updateState(const Connecting());
try {
final protocol = ssl ? 'wss' : 'ws';
var uri = Uri.parse('$protocol://$host/v1/database/$database/subscribe');
final headers = <String, dynamic>{};
final queryParams = <String, String>{};
if (!brotliNativelySupported) {
// Server default is Brotli; pure-Dart `package:brotli` miscompiles on
// dart2js; older browsers lack DecompressionStream('br') (Chrome 138+
// / Firefox 142+). Ask server to skip compression when we can't
// decompress Brotli ourselves.
queryParams['compression'] = 'None';
}
if (kIsWeb && _currentToken != null) {
final wsToken = await _getWebSocketToken();
if (wsToken != null) {
queryParams['token'] = wsToken;
}
} else if (_currentToken != null) {
headers['Authorization'] = 'Bearer $_currentToken';
}
if (queryParams.isNotEmpty) {
uri = uri.replace(queryParameters: queryParams);
}
_channel = _socketFactory(
uri,
kPreferredWsProtocols,
headers,
connectTimeout: config.connectTimeout,
// On VM, IOWebSocketChannel uses this to send WS-level Ping
// frames. On web it's ignored (HtmlWebSocketChannel doesn't
// expose WS ping/pong to JS).
pingInterval: kIsWeb ? null : config.pingInterval,
);
await _channel!.ready;
_negotiatedProtocol = normalizeWsProtocol(_channel!.protocol);
SdkLogger.i('Negotiated WebSocket protocol: ${_negotiatedProtocol.name}');
_setupMessageListener();
// On VM the WS-level ping (wired above) handles dead-socket
// detection natively. On web we still need the app-layer
// KeepAliveMonitor because browsers don't expose WS ping.
if (kIsWeb) {
_setupKeepAlive();
}
_updateState(const Connected());
_reconnectAttempts = 0;
_updateQuality();
} catch (e) {
SdkLogger.e('Connection failed: $e');
_updateState(const Disconnected());
_channel = null;
final errorString = e.toString();
if (errorString.contains('401') || errorString.contains('Unauthorized')) {
throw SpacetimeDbAuthException(
'Authentication failed (401). Token may be invalid or expired.',
);
}
throw SpacetimeDbConnectionException(
'Connection failed: $e',
lastKnownState: const Disconnected(),
);
}
}