Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/supabase_flutter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
flutter-version: ['3.10.x', '3.x']
flutter-version: ['3.19.x', '3.x']

defaults:
run:
Expand Down
35 changes: 22 additions & 13 deletions packages/gotrue/lib/src/broadcast_web.dart
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
import 'dart:async';
import 'dart:convert';
import 'dart:html' as html;
import 'dart:js_util' as js_util;
import 'dart:js_interop';

import 'package:gotrue/src/types/types.dart';
import 'package:logging/logging.dart';
import 'package:web/web.dart' as web;

final _log = Logger('supabase.auth');

BroadcastChannel getBroadcastChannel(String broadcastKey) {
final broadcast = html.BroadcastChannel(broadcastKey);
return (
onMessage: broadcast.onMessage.map((event) {
final dataMap = js_util.dartify(event.data);
final broadcast = web.BroadcastChannel(broadcastKey);
final controller = StreamController<Map<String, dynamic>>();

broadcast.addEventListener(
'message',
(web.Event event) {
if (event is web.MessageEvent) {
final dataMap = event.data.dartify();
controller.add(json.decode(json.encode(dataMap)));
}
} as web.EventListener,
);

// some parts have the wrong map type. This is an easy workaround and
// should be efficient enough for the small session and user data
return json.decode(json.encode(dataMap));
}),
return (
onMessage: controller.stream,
postMessage: (message) {
_log.finest('Broadcasting message: $message');
_log.fine('Broadcasting event: ${message['event']}');
final jsMessage = js_util.jsify(message);
broadcast.postMessage(jsMessage);
broadcast.postMessage(message.jsify() as JSAny);
},
close: () {
broadcast.close();
controller.close();
},
close: broadcast.close,
);
}
10 changes: 5 additions & 5 deletions packages/gotrue/lib/src/gotrue_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import 'package:gotrue/src/types/auth_response.dart';
import 'package:gotrue/src/types/fetch_options.dart';
import 'package:http/http.dart';
import 'package:jwt_decode/jwt_decode.dart';
import 'package:logging/logging.dart';
import 'package:meta/meta.dart';
import 'package:retry/retry.dart';
import 'package:rxdart/subjects.dart';
import 'package:logging/logging.dart';

import 'broadcast_stub.dart' if (dart.library.html) './broadcast_web.dart'
import 'broadcast_stub.dart' if (dart.library.js_interop) './broadcast_web.dart'
as web;
import 'version.dart';

Expand Down Expand Up @@ -363,8 +363,8 @@ class GoTrueClient {
),
);

await _asyncStorage!
.removeItem(key: '${Constants.defaultStorageKey}-code-verifier');
await _asyncStorage.removeItem(
key: '${Constants.defaultStorageKey}-code-verifier');

final authSessionUrlResponse = AuthSessionUrlResponse(
session: Session.fromJson(response)!, redirectType: redirectType?.name);
Expand Down Expand Up @@ -1163,7 +1163,7 @@ class GoTrueClient {
}

void _mayStartBroadcastChannel() {
if (const bool.fromEnvironment('dart.library.html')) {
if (const bool.fromEnvironment('dart.library.js_interop')) {
// Used by the js library as well
final broadcastKey =
"sb-${Uri.parse(_url).host.split(".").first}-auth-token";
Expand Down
3 changes: 2 additions & 1 deletion packages/gotrue/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ repository: 'https://github.com/supabase/supabase-flutter/tree/main/packages/got
documentation: 'https://supabase.com/docs/reference/dart/auth-signup'

environment:
sdk: '>=3.0.0 <4.0.0'
sdk: '>=3.3.0 <4.0.0'

dependencies:
collection: ^1.15.0
Expand All @@ -17,6 +17,7 @@ dependencies:
rxdart: '>=0.27.7 <0.29.0'
meta: ^1.7.0
logging: ^1.2.0
web: '>=0.5.0 <2.0.0'

dev_dependencies:
dart_jsonwebtoken: ^2.4.1
Expand Down
57 changes: 57 additions & 0 deletions packages/gotrue/test/src/broadcast_web_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
@TestOn('browser')
import 'dart:async';

import 'package:gotrue/src/broadcast_web.dart';
import 'package:gotrue/src/types/types.dart';
import 'package:test/test.dart';

void main() {
group('getBroadcastChannel', () {
late BroadcastChannel channel1;
late BroadcastChannel channel2;

setUp(() {
channel1 = getBroadcastChannel('test-channel');
channel2 = getBroadcastChannel('test-channel');
});

tearDown(() {
channel1.close();
channel2.close();
});

test('can send and receive messages between channels', () async {
final completer = Completer<Map<String, dynamic>>();

// Listen for messages on channel2
final subscription = channel2.onMessage.listen((message) {
completer.complete(message);
});

// Send message from channel1
final testMessage = {
'event': 'test-event',
'data': {'foo': 'bar'}
};
channel1.postMessage(testMessage);

// Wait for the message to be received
final receivedMessage = await completer.future;

expect(receivedMessage['event'], equals('test-event'));
expect(receivedMessage['data']['foo'], equals('bar'));

await subscription.cancel();
});

test('can close channels', () async {
channel1.close();

// Verify that sending messages after closing throws
expect(
() => channel1.postMessage({'event': 'test'}),
throwsA(anything),
);
});
});
}
2 changes: 1 addition & 1 deletion packages/realtime_client/lib/src/websocket/websocket.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export 'websocket_stub.dart'
if (dart.library.io) 'websocket_io.dart'
if (dart.library.html) 'websocket_web.dart';
if (bool.fromEnvironment) 'websocket_web.dart';
2 changes: 1 addition & 1 deletion packages/supabase/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ repository: 'https://github.com/supabase/supabase-flutter/tree/main/packages/sup
documentation: 'https://supabase.com/docs/reference/dart/introduction'

environment:
sdk: '>=3.0.0 <4.0.0'
sdk: '>=3.3.0 <4.0.0'

dependencies:
functions_client: 2.4.1
Expand Down
4 changes: 2 additions & 2 deletions packages/supabase_flutter/lib/src/local_storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'package:supabase_flutter/supabase_flutter.dart';

import './local_storage_stub.dart'
if (dart.library.html) './local_storage_web.dart' as web;
if (dart.library.js_interop) './local_storage_web.dart' as web;

/// Only used for migration from Hive to SharedPreferences. Not actually in use.
const supabasePersistSessionKey = 'SUPABASE_PERSIST_SESSION_KEY';
Expand Down Expand Up @@ -70,7 +70,7 @@ class SharedPreferencesLocalStorage extends LocalStorage {

final String persistSessionKey;
static const _useWebLocalStorage =
kIsWeb && bool.fromEnvironment("dart.library.html");
kIsWeb && bool.fromEnvironment("dart.library.js_interop");

@override
Future<void> initialize() async {
Expand Down
4 changes: 2 additions & 2 deletions packages/supabase_flutter/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ repository: 'https://github.com/supabase/supabase-flutter/tree/main/packages/sup
documentation: 'https://supabase.com/docs/reference/dart/introduction'

environment:
sdk: '>=3.0.0 <4.0.0'
flutter: '>=3.0.0'
sdk: '>=3.3.0 <4.0.0'
flutter: '>=3.19.0'

dependencies:
app_links: '>=3.5.0 <7.0.0'
Expand Down