Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor!: create package specific configs #640

Merged
merged 4 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
67 changes: 30 additions & 37 deletions packages/supabase/lib/src/supabase_client.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import 'dart:async';

import 'package:functions_client/functions_client.dart';
import 'package:gotrue/gotrue.dart';
import 'package:http/http.dart';
import 'package:postgrest/postgrest.dart';
import 'package:realtime_client/realtime_client.dart';
import 'package:storage_client/storage_client.dart';
import 'package:supabase/src/constants.dart';
import 'package:supabase/src/realtime_client_options.dart';
import 'package:supabase/src/supabase_query_builder.dart';
import 'package:supabase/supabase.dart';
import 'package:yet_another_json_isolate/yet_another_json_isolate.dart';

import 'auth_http_client.dart';
Expand Down Expand Up @@ -38,12 +32,13 @@ import 'auth_http_client.dart';
class SupabaseClient {
final String supabaseUrl;
final String supabaseKey;
final String schema;
final String restUrl;
final String realtimeUrl;
final String authUrl;
final String storageUrl;
final String functionsUrl;
final PostgrestClientOptions _postgrestOptions;

final String _restUrl;
final String _realtimeUrl;
final String _authUrl;
final String _storageUrl;
final String _functionsUrl;
final Map<String, String> _headers;
final Client? _httpClient;
late final Client _authHttpClient;
Expand Down Expand Up @@ -125,49 +120,47 @@ class SupabaseClient {
SupabaseClient(
this.supabaseUrl,
this.supabaseKey, {
String? schema,
bool autoRefreshToken = true,
PostgrestClientOptions postgrestOptions = const PostgrestClientOptions(),
AuthClientOptions authOptions = const AuthClientOptions(),
StorageClientOptions storageOptions = const StorageClientOptions(),
RealtimeClientOptions realtimeClientOptions = const RealtimeClientOptions(),
Map<String, String>? headers,
Client? httpClient,
int storageRetryAttempts = 0,
RealtimeClientOptions realtimeClientOptions = const RealtimeClientOptions(),
YAJsonIsolate? isolate,
GotrueAsyncStorage? gotrueAsyncStorage,
AuthFlowType authFlowType = AuthFlowType.pkce,
}) : restUrl = '$supabaseUrl/rest/v1',
realtimeUrl = '$supabaseUrl/realtime/v1'.replaceAll('http', 'ws'),
authUrl = '$supabaseUrl/auth/v1',
storageUrl = '$supabaseUrl/storage/v1',
functionsUrl = '$supabaseUrl/functions/v1',
schema = schema ?? 'public',
}) : _restUrl = '$supabaseUrl/rest/v1',
_realtimeUrl = '$supabaseUrl/realtime/v1'.replaceAll('http', 'ws'),
_authUrl = '$supabaseUrl/auth/v1',
_storageUrl = '$supabaseUrl/storage/v1',
_functionsUrl = '$supabaseUrl/functions/v1',
_postgrestOptions = postgrestOptions,
_headers = {
...Constants.defaultHeaders,
if (headers != null) ...headers
},
_httpClient = httpClient,
_isolate = isolate ?? (YAJsonIsolate()..initialize()) {
auth = _initSupabaseAuthClient(
autoRefreshToken: autoRefreshToken,
gotrueAsyncStorage: gotrueAsyncStorage,
authFlowType: authFlowType,
autoRefreshToken: authOptions.autoRefreshToken,
gotrueAsyncStorage: authOptions.pkceAsyncStorage,
authFlowType: authOptions.authFlowType,
);
_authHttpClient = AuthHttpClient(supabaseKey, httpClient ?? Client(), auth);
rest = _initRestClient();
functions = _initFunctionsClient();
storage = _initStorageClient(storageRetryAttempts);
storage = _initStorageClient(storageOptions.retryAttempts);
realtime = _initRealtimeClient(options: realtimeClientOptions);
_listenForAuthEvents();
}

/// Perform a table operation.
SupabaseQueryBuilder from(String table) {
final url = '$restUrl/$table';
final url = '$_restUrl/$table';
_incrementId++;
return SupabaseQueryBuilder(
url,
realtime,
headers: {...rest.headers, ...headers},
schema: schema,
schema: _postgrestOptions.schema,
table: table,
httpClient: _authHttpClient,
incrementId: _incrementId,
Expand Down Expand Up @@ -229,7 +222,7 @@ class SupabaseClient {
authHeaders['Authorization'] = 'Bearer $supabaseKey';

return GoTrueClient(
url: authUrl,
url: _authUrl,
headers: authHeaders,
autoRefreshToken: autoRefreshToken,
httpClient: _httpClient,
Expand All @@ -240,17 +233,17 @@ class SupabaseClient {

PostgrestClient _initRestClient() {
return PostgrestClient(
restUrl,
_restUrl,
headers: {...headers},
schema: schema,
schema: _postgrestOptions.schema,
httpClient: _authHttpClient,
isolate: _isolate,
);
}

FunctionsClient _initFunctionsClient() {
return FunctionsClient(
functionsUrl,
_functionsUrl,
{...headers},
httpClient: _authHttpClient,
isolate: _isolate,
Expand All @@ -259,7 +252,7 @@ class SupabaseClient {

SupabaseStorageClient _initStorageClient(int storageRetryAttempts) {
return SupabaseStorageClient(
storageUrl,
_storageUrl,
{...headers},
httpClient: _authHttpClient,
retryAttempts: storageRetryAttempts,
Expand All @@ -271,7 +264,7 @@ class SupabaseClient {
}) {
final eventsPerSecond = options.eventsPerSecond;
return RealtimeClient(
realtimeUrl,
_realtimeUrl,
params: {
'apikey': supabaseKey,
if (eventsPerSecond != null) 'eventsPerSecond': '$eventsPerSecond'
Expand Down
25 changes: 25 additions & 0 deletions packages/supabase/lib/src/supabase_client_options.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:supabase/supabase.dart';

class PostgrestClientOptions {
final String schema;

const PostgrestClientOptions({this.schema = 'public'});
}

class AuthClientOptions {
final bool autoRefreshToken;
final GotrueAsyncStorage? pkceAsyncStorage;
final AuthFlowType authFlowType;

const AuthClientOptions({
this.autoRefreshToken = true,
this.pkceAsyncStorage,
this.authFlowType = AuthFlowType.pkce,
});
}

class StorageClientOptions {
final int retryAttempts;

const StorageClientOptions({this.retryAttempts = 0});
}
1 change: 1 addition & 0 deletions packages/supabase/lib/supabase.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export 'src/auth_user.dart';
export 'src/realtime_client_options.dart';
export 'src/remove_subscription_result.dart';
export 'src/supabase_client.dart';
export 'src/supabase_client_options.dart';
export 'src/supabase_event_types.dart';
export 'src/supabase_query_builder.dart';
export 'src/supabase_realtime_error.dart';
4 changes: 2 additions & 2 deletions packages/supabase/test/client_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ void main() {
final client = SupabaseClient(
'http://${mockServer.address.host}:${mockServer.port}',
"supabaseKey",
autoRefreshToken: false,
authOptions: AuthClientOptions(autoRefreshToken: false),
);
await client.auth.recoverSession(sessionString);

Expand Down Expand Up @@ -101,7 +101,7 @@ void main() {
final client = SupabaseClient(
'http://${mockServer.address.host}:${mockServer.port}',
"supabaseKey",
autoRefreshToken: false,
authOptions: AuthClientOptions(autoRefreshToken: false),
);
final sessionData = getSessionData(expiresAt);
await client.auth.recoverSession(sessionData.sessionString);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'package:supabase_flutter/supabase_flutter.dart';

class FlutterAuthClientOptions extends AuthClientOptions {
final LocalStorage? localStorage;

const FlutterAuthClientOptions({
super.authFlowType,
super.autoRefreshToken,
super.pkceAsyncStorage,
this.localStorage,
});

FlutterAuthClientOptions copyWith({
AuthFlowType? authFlowType,
bool? autoRefreshToken,
LocalStorage? localStorage,
dynamic pkceAsyncStorage,
}) {
return FlutterAuthClientOptions(
authFlowType: authFlowType ?? this.authFlowType,
autoRefreshToken: autoRefreshToken ?? this.autoRefreshToken,
localStorage: localStorage ?? this.localStorage,
pkceAsyncStorage: pkceAsyncStorage ?? this.pkceAsyncStorage,
);
}
}
59 changes: 33 additions & 26 deletions packages/supabase_flutter/lib/src/supabase.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
import 'package:http/http.dart';
import 'package:supabase/supabase.dart';
import 'package:supabase_flutter/src/constants.dart';
import 'package:supabase_flutter/src/flutter_go_true_client_options.dart';
import 'package:supabase_flutter/src/local_storage.dart';
import 'package:supabase_flutter/src/supabase_auth.dart';

Expand Down Expand Up @@ -65,42 +66,47 @@ class Supabase {
static Future<Supabase> initialize({
required String url,
required String anonKey,
String? schema,
Map<String, String>? headers,
LocalStorage? localStorage,
Client? httpClient,
int storageRetryAttempts = 0,
RealtimeClientOptions realtimeClientOptions = const RealtimeClientOptions(),
AuthFlowType authFlowType = AuthFlowType.pkce,
GotrueAsyncStorage? pkceAsyncStorage,
PostgrestClientOptions postgrestOptions = const PostgrestClientOptions(),
StorageClientOptions storageOptions = const StorageClientOptions(),
FlutterAuthClientOptions authOptions =
const FlutterAuthClientOptions(),
bool? debug,
}) async {
assert(
!_instance._initialized,
'This instance is already initialized',
);
if (authOptions.pkceAsyncStorage == null) {
authOptions = authOptions.copyWith(
pkceAsyncStorage: SharedPreferencesGotrueAsyncStorage(),
);
}
if (authOptions.localStorage == null) {
authOptions = authOptions.copyWith(
localStorage: MigrationLocalStorage(
persistSessionKey:
"sb-${Uri.parse(url).host.split(".").first}-auth-token",
),
);
}
_instance._init(
url,
anonKey,
httpClient: httpClient,
customHeaders: headers,
schema: schema,
storageRetryAttempts: storageRetryAttempts,
realtimeClientOptions: realtimeClientOptions,
gotrueAsyncStorage:
pkceAsyncStorage ?? SharedPreferencesGotrueAsyncStorage(),
authFlowType: authFlowType,
authOptions: authOptions,
postgrestOptions: postgrestOptions,
storageOptions: storageOptions,
);
_instance._debugEnable = debug ?? kDebugMode;
_instance.log('***** Supabase init completed $_instance');

await SupabaseAuth.initialize(
localStorage: localStorage ??
MigrationLocalStorage(
persistSessionKey:
"sb-${Uri.parse(url).host.split(".").first}-auth-token"),
authFlowType: authFlowType,
);
_instance._supabaseAuth = SupabaseAuth();
await _instance._supabaseAuth.initialize(options: authOptions);

return _instance;
}
Expand All @@ -114,12 +120,15 @@ class Supabase {
///
/// Throws an error if [Supabase.initialize] was not called.
late SupabaseClient client;

late SupabaseAuth _supabaseAuth;

bool _debugEnable = false;

/// Dispose the instance to free up resources.
void dispose() {
client.dispose();
SupabaseAuth.instance.dispose();
_instance._supabaseAuth.dispose();
_initialized = false;
}

Expand All @@ -128,11 +137,10 @@ class Supabase {
String supabaseAnonKey, {
Client? httpClient,
Map<String, String>? customHeaders,
String? schema,
required int storageRetryAttempts,
required RealtimeClientOptions realtimeClientOptions,
required GotrueAsyncStorage gotrueAsyncStorage,
required AuthFlowType authFlowType,
required PostgrestClientOptions postgrestOptions,
required StorageClientOptions storageOptions,
required AuthClientOptions authOptions,
}) {
final headers = {
...Constants.defaultHeaders,
Expand All @@ -143,11 +151,10 @@ class Supabase {
supabaseAnonKey,
httpClient: httpClient,
headers: headers,
schema: schema,
storageRetryAttempts: storageRetryAttempts,
realtimeClientOptions: realtimeClientOptions,
gotrueAsyncStorage: gotrueAsyncStorage,
authFlowType: authFlowType,
postgrestOptions: postgrestOptions,
storageOptions: storageOptions,
authOptions: authOptions,
);
_initialized = true;
}
Expand Down
Loading