Class: Supabase::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/supabase/client.rb

Overview

Top-level client that combines every sub-library behind one object, mirroring supabase-py’s ‘supabase.create_client()`.

client = Supabase.create_client(
  supabase_url: "https://project.supabase.co",
  supabase_key: ENV["SUPABASE_ANON_KEY"]
)

client.auth.(email:, password:)
users = client.from("users").select("*").execute
client.storage.from("avatars").upload("a.png", bytes)
client.functions.invoke("hello-world", body: { name: "Ada" })
ch = client.realtime.channel("realtime:public:users")

Sub-clients are built lazily and memoized. Pass ‘async: true` to swap in the async-http-faraday variants for Auth / Postgrest / Storage / Functions; the Realtime client is transport-agnostic and ships sync regardless (a real WS transport is wired in by the caller — see lib/supabase/realtime/socket.rb).

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(supabase_url:, supabase_key:, options: {}, async: false) ⇒ Client

Returns a new instance of Client.

Raises:

  • (err)


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/supabase/client.rb', line 33

def initialize(supabase_url:, supabase_key:, options: {}, async: false)
  # Use Supabase::SupabaseException once defined; fall back to ArgumentError
  # during early require cycles. Matches supabase-py's contract.
  err = defined?(Supabase::SupabaseException) ? Supabase::SupabaseException : ArgumentError
  raise err, "supabase_url is required" if supabase_url.to_s.empty?
  raise err, "supabase_key is required" if supabase_key.to_s.empty?
  raise err, "Invalid URL" unless supabase_url.to_s.match?(%r{^https?://.+})

  @supabase_url = supabase_url.to_s.chomp("/")
  @supabase_key = supabase_key
  @options      = options || {}
  @async        = async

  configured_headers =
    if @options.is_a?(Supabase::ClientOptions)
      @options.headers
    else
      @options[:global]&.dig(:headers) || @options.dig("global", "headers") || {}
    end

  @headers = {
    "apikey"        => @supabase_key,
    "Authorization" => "Bearer #{@supabase_key}"
  }.merge(configured_headers || {})
end

Instance Attribute Details

#headersObject (readonly)

Returns the value of attribute headers.



31
32
33
# File 'lib/supabase/client.rb', line 31

def headers
  @headers
end

#optionsObject (readonly)

Returns the value of attribute options.



31
32
33
# File 'lib/supabase/client.rb', line 31

def options
  @options
end

#supabase_keyObject (readonly)

Returns the value of attribute supabase_key.



31
32
33
# File 'lib/supabase/client.rb', line 31

def supabase_key
  @supabase_key
end

#supabase_urlObject (readonly)

Returns the value of attribute supabase_url.



31
32
33
# File 'lib/supabase/client.rb', line 31

def supabase_url
  @supabase_url
end

Instance Method Details

#async?Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/supabase/client.rb', line 59

def async?
  @async
end

#authObject

— Sub-clients ———————————————————



65
66
67
# File 'lib/supabase/client.rb', line 65

def auth
  @auth ||= auth_class.new(url: rest_url_for("auth/v1"), headers: @headers, **sub_options(:auth))
end

#from(table) ⇒ Object



95
96
97
# File 'lib/supabase/client.rb', line 95

def from(table)
  postgrest.from(table)
end

#functionsObject



74
75
76
77
# File 'lib/supabase/client.rb', line 74

def functions
  @functions ||= functions_class.new(base_url: rest_url_for("functions/v1"), headers: @headers,
                                     **sub_options(:functions))
end

#postgrestObject

PostgREST is the only sub-library where the public API is reached via a bare method on the umbrella (‘client.from(’users’)‘) rather than a named accessor. We expose both for explicitness.



90
91
92
93
# File 'lib/supabase/client.rb', line 90

def postgrest
  @postgrest ||= postgrest_class.new(base_url: rest_url_for("rest/v1"), headers: @headers,
                                     **sub_options(:postgrest))
end

#realtimeObject



79
80
81
82
83
84
85
# File 'lib/supabase/client.rb', line 79

def realtime
  @realtime ||= Realtime::Client.new(
    url:    realtime_url,
    params: { "apikey" => @supabase_key, "access_token" => @supabase_key },
    **sub_options(:realtime)
  )
end

#rpc(func, params = {}, **opts) ⇒ Object



99
100
101
# File 'lib/supabase/client.rb', line 99

def rpc(func, params = {}, **opts)
  postgrest.rpc(func, params, **opts)
end

#schema(name) ⇒ Object



103
104
105
106
# File 'lib/supabase/client.rb', line 103

def schema(name)
  @postgrest = postgrest.schema(name)
  self
end

#set_auth(token) ⇒ Object

Update the Authorization header used by every sub-client. Useful after auth.sign_in returns a fresh JWT — the apikey stays the same but the bearer token becomes the user’s access token.



113
114
115
116
117
118
119
120
121
122
123
# File 'lib/supabase/client.rb', line 113

def set_auth(token)
  @headers["Authorization"] = "Bearer #{token || @supabase_key}"
  # Reset memoized sub-clients so they pick up the new header on next access.
  # Realtime gets its own pathway (set_auth pushes access_token frames).
  @auth      = nil
  @storage   = nil
  @functions = nil
  @postgrest = nil
  @realtime&.set_auth(token)
  self
end

#storageObject



69
70
71
72
# File 'lib/supabase/client.rb', line 69

def storage
  @storage ||= storage_class.new(base_url: rest_url_for("storage/v1"), headers: @headers,
                                 **sub_options(:storage))
end