From add52292fc67c9c23c205e2e3fd5f8c28537d483 Mon Sep 17 00:00:00 2001
From: Joseph Schultz
Date: Thu, 10 Nov 2022 13:30:08 -0600
Subject: [PATCH 1/9] Update child modules and update codebase to implement
them
---
README.md | 27 ++-
Supabase/Client.cs | 290 +++++++++++++++---------------
Supabase/StatelessClient.cs | 43 +++--
Supabase/Supabase.csproj | 15 +-
Supabase/SupabaseFunctions.cs | 33 ++--
Supabase/SupabaseModel.cs | 9 -
Supabase/SupabaseOptions.cs | 59 ++++++
Supabase/SupabaseTable.cs | 27 ++-
SupabaseExample/Models/Channel.cs | 3 +-
SupabaseExample/Models/Movie.cs | 6 +-
SupabaseExample/Program.cs | 20 +--
SupabaseTests/Client.cs | 12 +-
SupabaseTests/Models/Channel.cs | 3 +-
SupabaseTests/Models/Stub.cs | 2 +-
SupabaseTests/Models/User.cs | 2 +-
SupabaseTests/StatelessClient.cs | 9 +-
modules/functions-csharp | 2 +-
modules/gotrue-csharp | 2 +-
modules/postgrest-csharp | 2 +-
modules/realtime-csharp | 2 +-
modules/storage-csharp | 2 +-
supabase-csharp.sln | 64 +++++--
22 files changed, 367 insertions(+), 267 deletions(-)
create mode 100644 Supabase/SupabaseOptions.cs
diff --git a/README.md b/README.md
index 762d4393..54b2019c 100644
--- a/README.md
+++ b/README.md
@@ -7,8 +7,6 @@
-Stage: Beta
-
---
Integrate your [Supabase](https://supabase.io) projects with C#.
@@ -42,40 +40,35 @@ public async void Main()
var url = Environment.GetEnvironmentVariable("SUPABASE_URL");
var key = Environment.GetEnvironmentVariable("SUPABASE_KEY");
- await Supabase.Client.InitializeAsync(url, key);
+ var client = new Supabase.Client(url, key);
+ await client.InitializeAsync();
// That's it - forreal. Crazy right?
- // The Supabase Instance can be accessed at any time using:
- // Supabase.Client.Instance {.Realtime|.Auth|etc.}
- // For ease of readability we'll use this:
- var instance = Supabase.Client.Instance;
-
// Access Postgrest using:
- var channels = await instance.From().Get();
+ var channels = await client.From().Get();
// Access Auth using:
- await instance.Auth.SignIn(email, password);
- Debug.WriteLine(instance.Auth.CurrentUser.Id);
+ await client.Auth.SignIn(email, password);
+ Debug.WriteLine(client.Auth.CurrentUser.Id);
// Interested in Realtime Events?
- var table = await instance.From();
+ var table = await client.From();
table.On(ChannelEventType.Insert, Channel_Inserted);
table.On(ChannelEventType.Delete, Channel_Deleted);
table.On(ChannelEventType.Update, Channel_Updated);
// Invoke an Edge Function
- var result = await instance.Functions.Invoke("hello", new Dictionary {
+ var result = await client.Functions.Invoke("hello", new Dictionary {
{ "name", "Ronald" }
});
// Run a Remote Stored Procedure:
- await instance.Rpc("my_cool_procedure", params);
+ await client.Rpc("my_cool_procedure", params);
// Interact with Supabase Storage
- var storage = Supabase.Client.Instance.Storage
- await storage.CreateBucket("testing")
+ await client.Storage.CreateBucket("testing")
- var bucket = storage.From("testing");
+ var bucket = client.Storage.From("testing");
var basePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase).Replace("file:", "");
var imagePath = Path.Combine(basePath, "Assets", "supabase-csharp.png");
diff --git a/Supabase/Client.cs b/Supabase/Client.cs
index ade0de8c..68de6707 100644
--- a/Supabase/Client.cs
+++ b/Supabase/Client.cs
@@ -4,10 +4,18 @@
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Postgrest;
+using Postgrest.Interfaces;
using Postgrest.Models;
using Postgrest.Responses;
+using Storage.Interfaces;
+using Supabase.Functions.Interfaces;
using Supabase.Gotrue;
+using Supabase.Gotrue.Interfaces;
+using Supabase.Realtime;
+using Supabase.Realtime.Interfaces;
+using Supabase.Storage;
using static Supabase.Functions.Client;
+using static Supabase.Gotrue.Constants;
namespace Supabase
{
@@ -24,36 +32,85 @@ public enum ChannelEventType
All
}
+ public IGotrueClient Auth { get => AuthClient; }
+ public SupabaseFunctions Functions { get => new SupabaseFunctions(FunctionsClient, FunctionsUrl, GetAuthHeaders()); }
+
+ public IPostgrestClient Postgrest { get => PostgrestClient; }
+
+ public IRealtimeClient Realtime { get => RealtimeClient; }
+
+ public IStorageClient Storage { get => StorageClient; }
+
///
/// Supabase Auth allows you to create and manage user sessions for access to data that is secured by access policies.
///
- public Gotrue.Client Auth { get; private set; }
- public Realtime.Client Realtime { get; private set; }
+ public IGotrueClient AuthClient
+ {
+ get
+ {
+ return _authClient;
+ }
+ set
+ {
+ // Remove existing internal state listener (if applicable)
+ if (_authClient != null)
+ _authClient.StateChanged -= Auth_StateChanged;
+
+ _authClient = value;
+ _authClient.StateChanged += Auth_StateChanged;
+ }
+ }
+ private IGotrueClient _authClient;
+
+ ///
+ /// Supabase Realtime allows for realtime feedback on database changes.
+ ///
+ public IRealtimeClient RealtimeClient
+ {
+ get
+ {
+ return _realtimeClient;
+ }
+ set
+ {
+ // Disconnect from previous socket (if applicable)
+ if (_realtimeClient != null)
+ _realtimeClient.Disconnect();
+
+ _realtimeClient = value;
+ }
+ }
+ private IRealtimeClient _realtimeClient;
///
/// Supabase Edge functions allow you to deploy and invoke edge functions.
///
- public SupabaseFunctions Functions => new SupabaseFunctions(instance.FunctionsUrl, instance.GetAuthHeaders());
+ public IFunctionsClient FunctionsClient
+ {
+ get => _functionsClient;
+ set => _functionsClient = value;
+ }
+ private IFunctionsClient _functionsClient;
- private Postgrest.Client Postgrest() => global::Postgrest.Client.Initialize(instance.RestUrl, new Postgrest.ClientOptions
+ ///
+ /// Supabase Postgrest allows for strongly typed REST interactions with the your database.
+ ///
+ public IPostgrestClient PostgrestClient
{
- Headers = instance.GetAuthHeaders(),
- Schema = Schema
- });
+ get => _postgrestClient;
+ set => _postgrestClient = value;
+ }
+ private IPostgrestClient _postgrestClient;
- private static Client instance;
- public static Client Instance
+ ///
+ /// Supabase Storage allows you to manage user-generated content, such as photos or videos.
+ ///
+ public IStorageClient StorageClient
{
- get
- {
- if (instance == null)
- {
- Debug.WriteLine("Supabase must be initialized before it is called.");
- return null;
- }
- return instance;
- }
+ get => _storageClient;
+ set => _storageClient = value;
}
+ private IStorageClient _storageClient;
public string SupabaseKey { get; private set; }
public string SupabaseUrl { get; private set; }
@@ -66,48 +123,20 @@ public static Client Instance
private SupabaseOptions options;
- private Client() { }
-
-
- ///
- /// Initializes a Supabase Client.
- ///
- ///
- ///
- ///
- ///
- public static void Initialize(string supabaseUrl, string supabaseKey, SupabaseOptions options = null, Action callback = null)
- {
- Task.Run(async () =>
- {
- var result = await InitializeAsync(supabaseUrl, supabaseKey, options);
- callback?.Invoke(result);
- });
- }
-
- ///
- /// Initializes a Supabase Client Asynchronously.
- ///
- ///
- ///
- ///
- ///
- public static async Task InitializeAsync(string supabaseUrl, string supabaseKey, SupabaseOptions options = null)
+ public Client(string supabaseUrl, string supabaseKey, SupabaseOptions? options = null)
{
- instance = new Client();
- instance.SupabaseUrl = supabaseUrl;
- instance.SupabaseKey = supabaseKey;
+ SupabaseUrl = supabaseUrl;
+ SupabaseKey = supabaseKey;
- if (options == null)
- options = new SupabaseOptions();
+ options ??= new SupabaseOptions();
+ this.options = options;
- instance.options = options;
- instance.AuthUrl = string.Format(options.AuthUrlFormat, supabaseUrl);
- instance.RestUrl = string.Format(options.RestUrlFormat, supabaseUrl);
- instance.RealtimeUrl = string.Format(options.RealtimeUrlFormat, supabaseUrl).Replace("http", "ws");
- instance.StorageUrl = string.Format(options.StorageUrlFormat, supabaseUrl);
- instance.Schema = options.Schema;
+ AuthUrl = string.Format(options.AuthUrlFormat, supabaseUrl);
+ RestUrl = string.Format(options.RestUrlFormat, supabaseUrl);
+ RealtimeUrl = string.Format(options.RealtimeUrlFormat, supabaseUrl).Replace("http", "ws");
+ StorageUrl = string.Format(options.StorageUrlFormat, supabaseUrl);
+ Schema = options.Schema;
// See: https://github.com/supabase/supabase-js/blob/09065a65f171bc28a9fd7b831af2c24e5f1a380b/src/SupabaseClient.ts#L77-L83
var isPlatform = new Regex(@"(supabase\.co)|(supabase\.in)").Match(supabaseUrl);
@@ -115,81 +144,98 @@ public static async Task InitializeAsync(string supabaseUrl, string supa
if (isPlatform.Success)
{
var parts = supabaseUrl.Split('.');
- instance.FunctionsUrl = $"{parts[0]}.functions.{parts[1]}.{parts[2]}";
+ FunctionsUrl = $"{parts[0]}.functions.{parts[1]}.{parts[2]}";
}
else
{
- instance.FunctionsUrl = string.Format(options.FunctionsUrlFormat, supabaseUrl);
+ FunctionsUrl = string.Format(options.FunctionsUrlFormat, supabaseUrl);
}
// Init Auth
- instance.Auth = await Gotrue.Client.InitializeAsync(new Gotrue.ClientOptions
+ var gotrueOptions = new Gotrue.ClientOptions
{
- Url = instance.AuthUrl,
- Headers = instance.GetAuthHeaders(),
+ Url = AuthUrl,
+ Headers = GetAuthHeaders(),
AutoRefreshToken = options.AutoRefreshToken,
PersistSession = options.PersistSession,
SessionDestroyer = options.SessionDestroyer,
SessionPersistor = options.SessionPersistor,
SessionRetriever = options.SessionRetriever
- });
- instance.Auth.StateChanged += Auth_StateChanged;
+ };
+
+ _authClient = new Gotrue.Client(gotrueOptions);
+ _authClient.StateChanged += Auth_StateChanged;
// Init Realtime
- if (options.ShouldInitializeRealtime)
+
+ var realtimeOptions = new Realtime.ClientOptions
{
- instance.Realtime = Supabase.Realtime.Client.Initialize(instance.RealtimeUrl, new Realtime.ClientOptions
- {
- Parameters = { ApiKey = instance.SupabaseKey }
- });
-
- if (options.AutoConnectRealtime)
- {
- await instance.Realtime.ConnectAsync();
- }
- }
+ Parameters = { ApiKey = SupabaseKey }
+ };
+
+ _realtimeClient = new Realtime.Client(RealtimeUrl, realtimeOptions);
+
+ _postgrestClient = new Postgrest.Client(RestUrl, new Postgrest.ClientOptions
+ {
+ Headers = GetAuthHeaders(),
+ Schema = Schema
+ });
+
+ _functionsClient = new Functions.Client();
+
+ _storageClient = new Storage.Client(StorageUrl, GetAuthHeaders());
+ }
+
+
+ ///
+ /// Initializes a Supabase Client.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task InitializeAsync()
+ {
+ await AuthClient.RetrieveSessionAsync();
- return instance;
+ if (options.AutoConnectRealtime)
+ {
+ await RealtimeClient.ConnectAsync();
+ }
+ return this;
}
- private static void Auth_StateChanged(object sender, ClientStateChanged e)
+ private void Auth_StateChanged(object sender, ClientStateChanged e)
{
switch (e.State)
{
// Pass new Auth down to Realtime
// Ref: https://github.com/supabase-community/supabase-csharp/issues/12
- case Gotrue.Client.AuthState.SignedIn:
- case Gotrue.Client.AuthState.TokenRefreshed:
- if (Instance.Realtime != null)
+ case AuthState.SignedIn:
+ case AuthState.TokenRefreshed:
+ if (AuthClient.CurrentSession != null && AuthClient.CurrentSession.AccessToken != null)
{
- Instance.Realtime.SetAuth(Instance.Auth.CurrentSession.AccessToken);
+ RealtimeClient.SetAuth(AuthClient.CurrentSession.AccessToken);
}
+ _postgrestClient.Options.Headers = GetAuthHeaders();
+ _storageClient.Headers = GetAuthHeaders();
break;
// Remove Realtime Subscriptions on Auth Signout.
- case Gotrue.Client.AuthState.SignedOut:
- if (Instance.Realtime != null)
- {
- foreach (var subscription in Instance.Realtime.Subscriptions.Values)
- subscription.Unsubscribe();
-
- Instance.Realtime.Disconnect();
- }
+ case AuthState.SignedOut:
+ foreach (var subscription in RealtimeClient.Subscriptions.Values)
+ subscription.Unsubscribe();
+ RealtimeClient.Disconnect();
break;
}
}
- ///
- /// Supabase Storage allows you to manage user-generated content, such as photos or videos.
- ///
- public Storage.Client Storage => new Storage.Client(StorageUrl, GetAuthHeaders());
-
///
/// Gets the Postgrest client to prepare for a query.
///
///
///
- public SupabaseTable From() where T : BaseModel, new() => new SupabaseTable();
+ public SupabaseTable From() where T : BaseModel, new() => new SupabaseTable(Postgrest, Realtime);
///
/// Runs a remote procedure.
@@ -197,7 +243,7 @@ private static void Auth_StateChanged(object sender, ClientStateChanged e)
///
///
///
- public Task Rpc(string procedureName, Dictionary parameters) => Postgrest().Rpc(procedureName, parameters);
+ public Task Rpc(string procedureName, Dictionary parameters) => Postgrest.Rpc(procedureName, parameters);
internal Dictionary GetAuthHeaders()
@@ -213,63 +259,11 @@ internal Dictionary GetAuthHeaders()
}
else
{
- var bearer = Auth?.CurrentSession?.AccessToken != null ? Auth.CurrentSession.AccessToken : SupabaseKey;
+ var bearer = AuthClient?.CurrentSession?.AccessToken != null ? AuthClient.CurrentSession.AccessToken : SupabaseKey;
headers["Authorization"] = $"Bearer {bearer}";
}
return headers;
}
}
-
- ///
- /// Options available for Supabase Client Configuration
- ///
- public class SupabaseOptions
- {
- public string Schema = "public";
-
- ///
- /// Should the Client automatically handle refreshing the User's Token?
- ///
- public bool AutoRefreshToken { get; set; } = true;
-
- ///
- /// Should the Client Initialize Realtime?
- ///
- public bool ShouldInitializeRealtime { get; set; } = false;
-
- ///
- /// Should the Client automatically connect to Realtime?
- ///
- public bool AutoConnectRealtime { get; set; } = false;
-
- ///
- /// Should the Client call , , and ?
- ///
- public bool PersistSession { get; set; } = true;
-
- ///
- /// Function called to persist the session (probably on a filesystem or cookie)
- ///
- public Func> SessionPersistor = (Session session) => Task.FromResult(true);
-
- ///
- /// Function to retrieve a session (probably from the filesystem or cookie)
- ///
- public Func> SessionRetriever = () => Task.FromResult(null);
-
- ///
- /// Function to destroy a session.
- ///
- public Func> SessionDestroyer = () => Task.FromResult(true);
-
- public Dictionary Headers = new Dictionary();
-
- public string AuthUrlFormat { get; set; } = "{0}/auth/v1";
- public string RestUrlFormat { get; set; } = "{0}/rest/v1";
- public string RealtimeUrlFormat { get; set; } = "{0}/realtime/v1";
- public string StorageUrlFormat { get; set; } = "{0}/storage/v1";
-
- public string FunctionsUrlFormat { get; set; } = "{0}/functions/v1";
- }
}
diff --git a/Supabase/StatelessClient.cs b/Supabase/StatelessClient.cs
index 8130928f..d4e7188f 100644
--- a/Supabase/StatelessClient.cs
+++ b/Supabase/StatelessClient.cs
@@ -16,28 +16,28 @@ namespace Supabase
///
public static class StatelessClient
{
- public static Gotrue.StatelessClient.StatelessClientOptions GetAuthOptions(string supabaseUrl, string supabaseKey = null, SupabaseOptions options = null)
+ public static Gotrue.ClientOptions GetAuthOptions(string supabaseUrl, string? supabaseKey = null, SupabaseOptions? options = null)
{
if (options == null)
options = new SupabaseOptions();
- var headers = GetAuthHeaders(supabaseKey, options).MergeLeft(options.Headers);
+ var headers = GetAuthHeaders(supabaseKey ?? "", options).MergeLeft(options.Headers);
- return new Gotrue.StatelessClient.StatelessClientOptions
+ return new Gotrue.ClientOptions
{
Url = string.Format(options.AuthUrlFormat, supabaseUrl),
Headers = headers
};
}
- public static Postgrest.StatelessClientOptions GetRestOptions(string supabaseUrl, string supabaseKey = null, SupabaseOptions options = null)
+ public static Postgrest.ClientOptions GetRestOptions(string? supabaseKey = null, SupabaseOptions? options = null)
{
if (options == null)
options = new SupabaseOptions();
- var headers = GetAuthHeaders(supabaseKey, options).MergeLeft(options.Headers);
+ var headers = GetAuthHeaders(supabaseKey ?? "", options).MergeLeft(options.Headers);
- return new Postgrest.StatelessClientOptions(string.Format(options.RestUrlFormat, supabaseUrl))
+ return new Postgrest.ClientOptions
{
Schema = options.Schema,
Headers = headers
@@ -51,12 +51,12 @@ public static Postgrest.StatelessClientOptions GetRestOptions(string supabaseUrl
///
///
///
- public static Storage.Client Storage(string supabaseUrl, string supabaseKey = null, SupabaseOptions options = null)
+ public static Storage.Client Storage(string supabaseUrl, string? supabaseKey = null, SupabaseOptions? options = null)
{
if (options == null)
options = new SupabaseOptions();
- var headers = GetAuthHeaders(supabaseKey, options).MergeLeft(options.Headers);
+ var headers = GetAuthHeaders(supabaseKey ?? "", options).MergeLeft(options.Headers);
return new Storage.Client(string.Format(options.StorageUrlFormat, supabaseUrl), headers);
}
@@ -68,7 +68,7 @@ public static Storage.Client Storage(string supabaseUrl, string supabaseKey = nu
///
///
///
- public static SupabaseFunctions Functions(string supabaseUrl, string supabaseKey, SupabaseOptions options = null)
+ public static SupabaseFunctions Functions(string supabaseUrl, string supabaseKey, SupabaseOptions? options = null)
{
if (options == null)
options = new SupabaseOptions();
@@ -88,8 +88,9 @@ public static SupabaseFunctions Functions(string supabaseUrl, string supabaseKey
}
var headers = GetAuthHeaders(supabaseKey, options).MergeLeft(options.Headers);
+ var client = new Functions.Client();
- return new SupabaseFunctions(functionsUrl, headers);
+ return new SupabaseFunctions(client, functionsUrl, headers);
}
///
@@ -97,19 +98,23 @@ public static SupabaseFunctions Functions(string supabaseUrl, string supabaseKey
///
///
///
- public static SupabaseTable From(string supabaseUrl, string supabaseKey, SupabaseOptions options = null) where T : BaseModel, new()
+ public static SupabaseTable From(string supabaseUrl, string supabaseKey, SupabaseOptions? options = null) where T : BaseModel, new()
{
if (options == null)
options = new SupabaseOptions();
- var headers = GetAuthHeaders(supabaseKey, options).MergeLeft(options.Headers);
+ var restUrl = string.Format(options.RestUrlFormat, supabaseUrl);
+ var realtimeUrl = string.Format(options.RealtimeUrlFormat, supabaseUrl).Replace("http", "ws");
+ var restOptions = GetRestOptions(supabaseKey, options);
+ restOptions.Headers.MergeLeft(options.Headers);
- return new SupabaseTable(string.Format(options.RestUrlFormat, supabaseUrl), new Postgrest.ClientOptions
- {
- Headers = headers,
- Schema = options.Schema
- });
+ var realtimeOptions = new Realtime.ClientOptions { Parameters = { ApiKey = supabaseKey } };
+
+ var postgrestClient = new Postgrest.Client(restUrl, restOptions);
+ var realtimeClient = new Realtime.Client(realtimeUrl, realtimeOptions);
+
+ return new SupabaseTable(postgrestClient, realtimeClient, options.Schema);
}
///
@@ -118,12 +123,12 @@ public static SupabaseFunctions Functions(string supabaseUrl, string supabaseKey
///
///
///
- public static Task Rpc(string supabaseUrl, string supabaseKey, string procedureName, Dictionary parameters, SupabaseOptions options = null)
+ public static Task Rpc(string supabaseUrl, string supabaseKey, string procedureName, Dictionary parameters, SupabaseOptions? options = null)
{
if (options == null)
options = new SupabaseOptions();
- return Postgrest.StatelessClient.Rpc(procedureName, parameters, GetRestOptions(supabaseUrl, supabaseKey, options));
+ return new Postgrest.Client(string.Format(options.RestUrlFormat, supabaseUrl), GetRestOptions(supabaseKey, options)).Rpc(procedureName, parameters);
}
diff --git a/Supabase/Supabase.csproj b/Supabase/Supabase.csproj
index 9229a430..bd81efda 100644
--- a/Supabase/Supabase.csproj
+++ b/Supabase/Supabase.csproj
@@ -19,18 +19,23 @@
0.5.3
+
+ enable
+ 8.0
+ CS8600;CS8602;CS8603
+
0.5.3
$(VersionPrefix)
-
+
-
-
-
+
+
+
-
+
diff --git a/Supabase/SupabaseFunctions.cs b/Supabase/SupabaseFunctions.cs
index 375319cf..45810e7a 100644
--- a/Supabase/SupabaseFunctions.cs
+++ b/Supabase/SupabaseFunctions.cs
@@ -1,4 +1,5 @@
-using System;
+using Supabase.Functions.Interfaces;
+using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
@@ -9,31 +10,33 @@ namespace Supabase
{
public class SupabaseFunctions
{
- private string _functionsUrl;
- private Dictionary _headers = new Dictionary();
+ private string functionsUrl;
+ private Dictionary headers = new Dictionary();
+ private IFunctionsClient client;
- public SupabaseFunctions(string functionsUrl, Dictionary headers)
+ public SupabaseFunctions(IFunctionsClient client, string functionsUrl, Dictionary headers)
{
- _functionsUrl = functionsUrl.TrimEnd('/');
- _headers = headers;
+ this.client = client;
+ this.functionsUrl = functionsUrl.TrimEnd('/');
+ this.headers = headers;
}
- public Task Invoke(string functionName, Dictionary body = null) => Functions.Client.Invoke($"{_functionsUrl}/{functionName}", options: new InvokeFunctionOptions
+ public Task Invoke(string functionName, Dictionary? body = null) => client.Invoke($"{functionsUrl}/{functionName}", options: new InvokeFunctionOptions
{
- Headers = _headers,
- Body = body
+ Headers = headers,
+ Body = body ?? new Dictionary()
});
- public Task Invoke(string functionName, Dictionary body = null) => Functions.Client.Invoke($"{_functionsUrl}/{functionName}", options: new InvokeFunctionOptions
+ public Task Invoke(string functionName, Dictionary? body = null) where T : class => client.Invoke($"{functionsUrl}/{functionName}", options: new InvokeFunctionOptions
{
- Headers = _headers,
- Body = body
+ Headers = headers,
+ Body = body ?? new Dictionary()
});
- public Task RawInvoke(string functionName, Dictionary body = null) => Functions.Client.RawInvoke($"{_functionsUrl}/{functionName}", options: new InvokeFunctionOptions
+ public Task RawInvoke(string functionName, Dictionary? body = null) => client.RawInvoke($"{functionsUrl}/{functionName}", options: new InvokeFunctionOptions
{
- Headers = _headers,
- Body = body
+ Headers = headers,
+ Body = body ?? new Dictionary()
});
}
}
diff --git a/Supabase/SupabaseModel.cs b/Supabase/SupabaseModel.cs
index 79e49880..a258beb5 100644
--- a/Supabase/SupabaseModel.cs
+++ b/Supabase/SupabaseModel.cs
@@ -8,14 +8,5 @@ namespace Supabase
{
public abstract class SupabaseModel : BaseModel
{
- public override Task> Update(CancellationToken cancellationToken = default(CancellationToken))
- {
- return Client.Instance.From().Update(this as T);
- }
-
- public override Task Delete(CancellationToken cancellationToken = default(CancellationToken))
- {
- return Client.Instance.From().Delete(this as T);
- }
}
}
diff --git a/Supabase/SupabaseOptions.cs b/Supabase/SupabaseOptions.cs
new file mode 100644
index 00000000..7b6a39a9
--- /dev/null
+++ b/Supabase/SupabaseOptions.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Supabase.Gotrue;
+
+namespace Supabase
+{
+ ///
+ /// Options available for Supabase Client Configuration
+ ///
+ public class SupabaseOptions
+ {
+ public string Schema = "public";
+
+ ///
+ /// Should the Client automatically handle refreshing the User's Token?
+ ///
+ public bool AutoRefreshToken { get; set; } = true;
+
+ ///
+ /// Should the Client Initialize Realtime?
+ ///
+ public bool ShouldInitializeRealtime { get; set; } = false;
+
+ ///
+ /// Should the Client automatically connect to Realtime?
+ ///
+ public bool AutoConnectRealtime { get; set; } = false;
+
+ ///
+ /// Should the Client call , , and ?
+ ///
+ public bool PersistSession { get; set; } = true;
+
+ ///
+ /// Function called to persist the session (probably on a filesystem or cookie)
+ ///
+ public Func> SessionPersistor = (Session session) => Task.FromResult(true);
+
+ ///
+ /// Function to retrieve a session (probably from the filesystem or cookie)
+ ///
+ public Func> SessionRetriever = () => Task.FromResult(null);
+
+ ///
+ /// Function to destroy a session.
+ ///
+ public Func> SessionDestroyer = () => Task.FromResult(true);
+
+ public Dictionary Headers = new Dictionary();
+
+ public string AuthUrlFormat { get; set; } = "{0}/auth/v1";
+ public string RestUrlFormat { get; set; } = "{0}/rest/v1";
+ public string RealtimeUrlFormat { get; set; } = "{0}/realtime/v1";
+ public string StorageUrlFormat { get; set; } = "{0}/storage/v1";
+
+ public string FunctionsUrlFormat { get; set; } = "{0}/functions/v1";
+ }
+}
diff --git a/Supabase/SupabaseTable.cs b/Supabase/SupabaseTable.cs
index a3e28ab4..4a737c6f 100644
--- a/Supabase/SupabaseTable.cs
+++ b/Supabase/SupabaseTable.cs
@@ -2,21 +2,30 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Postgrest;
+using Postgrest.Interfaces;
using Postgrest.Models;
using Supabase.Realtime;
+using Supabase.Realtime.Interfaces;
using static Supabase.Client;
namespace Supabase
{
public class SupabaseTable : Table where T : BaseModel, new()
{
- private Channel channel;
+ private Channel? channel;
- public SupabaseTable() : base(Client.Instance.RestUrl, new Postgrest.ClientOptions { Headers = Instance.GetAuthHeaders(), Schema = Instance.Schema })
- { }
+ private IPostgrestClient postgrestClient;
- public SupabaseTable(string restUrl, Postgrest.ClientOptions options) : base(restUrl, options)
- { }
+ private IRealtimeClient realtimeClient;
+
+ private string schema;
+
+ public SupabaseTable(IPostgrestClient postgrestClient, IRealtimeClient realtimeClient, string schema = "public") : base(postgrestClient.BaseUrl, null, postgrestClient.Options)
+ {
+ this.postgrestClient = postgrestClient;
+ this.realtimeClient = realtimeClient;
+ this.schema = schema;
+ }
public async Task On(ChannelEventType e, Action
public class SupabaseOptions
{
+ ///
+ /// Schema to be used in Postgres / Realtime
+ ///
public string Schema = "public";
///
diff --git a/Supabase/SupabaseTable.cs b/Supabase/SupabaseTable.cs
index 1b64b8a7..c2acffe1 100644
--- a/Supabase/SupabaseTable.cs
+++ b/Supabase/SupabaseTable.cs
@@ -36,13 +36,13 @@ public async Task On(ChannelEventType e, Action();
// In regard to: https://github.com/supabase/supabase-js/pull/270
- var headers = postgrestClient.Options.Headers;
- if (headers.ContainsKey("Authorization"))
+ var headers = postgrestClient?.GetHeaders?.Invoke();
+ if (headers != null && headers.ContainsKey("Authorization"))
{
parameters.Add("user_token", headers["Authorization"].Split(' ')[1]);
}
- channel = realtimeClient.Channel("realtime", this.schema, TableName, parameters: parameters);
+ channel = realtimeClient.Channel("realtime", schema, TableName, parameters: parameters);
}
if (realtimeClient.Socket == null || !realtimeClient.Socket.IsConnected)
diff --git a/Supabase/Util.cs b/Supabase/Util.cs
deleted file mode 100644
index 92fec65b..00000000
--- a/Supabase/Util.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-namespace Supabase
-{
- public static class Util
- {
- public static string GetAssemblyVersion()
- {
- var assembly = typeof(Supabase.Client).Assembly;
- var informationVersion = assembly.GetCustomAttribute().InformationalVersion;
- var name = assembly.GetName().Name;
-
- return $"{name.ToString().ToLower()}-csharp/{informationVersion}";
- }
- }
-}