supabase-rb 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/lib/supabase/README.md +90 -0
  3. data/lib/supabase/auth/README.md +172 -0
  4. data/lib/supabase/auth/admin_api.rb +218 -0
  5. data/lib/supabase/auth/admin_oauth_api.rb +51 -0
  6. data/lib/supabase/auth/api.rb +125 -0
  7. data/lib/supabase/auth/async/admin_api.rb +36 -0
  8. data/lib/supabase/auth/async/admin_oauth_api.rb +15 -0
  9. data/lib/supabase/auth/async/api.rb +32 -0
  10. data/lib/supabase/auth/async/client.rb +33 -0
  11. data/lib/supabase/auth/async.rb +14 -0
  12. data/lib/supabase/auth/client.rb +1217 -0
  13. data/lib/supabase/auth/constants.rb +32 -0
  14. data/lib/supabase/auth/errors.rb +207 -0
  15. data/lib/supabase/auth/helpers.rb +222 -0
  16. data/lib/supabase/auth/memory_storage.rb +25 -0
  17. data/lib/supabase/auth/storage.rb +19 -0
  18. data/lib/supabase/auth/timer.rb +40 -0
  19. data/lib/supabase/auth/types.rb +517 -0
  20. data/lib/supabase/auth/version.rb +7 -0
  21. data/lib/supabase/auth.rb +19 -0
  22. data/lib/supabase/client.rb +200 -0
  23. data/lib/supabase/client_options.rb +82 -0
  24. data/lib/supabase/functions/README.md +71 -0
  25. data/lib/supabase/functions/async/client.rb +45 -0
  26. data/lib/supabase/functions/async.rb +8 -0
  27. data/lib/supabase/functions/client.rb +174 -0
  28. data/lib/supabase/functions/errors.rb +38 -0
  29. data/lib/supabase/functions/types.rb +37 -0
  30. data/lib/supabase/functions/version.rb +7 -0
  31. data/lib/supabase/functions.rb +11 -0
  32. data/lib/supabase/postgrest/README.md +84 -0
  33. data/lib/supabase/postgrest/async/client.rb +50 -0
  34. data/lib/supabase/postgrest/async.rb +8 -0
  35. data/lib/supabase/postgrest/client.rb +136 -0
  36. data/lib/supabase/postgrest/errors.rb +49 -0
  37. data/lib/supabase/postgrest/request_builder.rb +657 -0
  38. data/lib/supabase/postgrest/types.rb +60 -0
  39. data/lib/supabase/postgrest/utils.rb +24 -0
  40. data/lib/supabase/postgrest/version.rb +7 -0
  41. data/lib/supabase/postgrest.rb +13 -0
  42. data/lib/supabase/realtime/README.md +90 -0
  43. data/lib/supabase/realtime/channel.rb +274 -0
  44. data/lib/supabase/realtime/client.rb +182 -0
  45. data/lib/supabase/realtime/errors.rb +19 -0
  46. data/lib/supabase/realtime/message.rb +38 -0
  47. data/lib/supabase/realtime/presence.rb +136 -0
  48. data/lib/supabase/realtime/push.rb +48 -0
  49. data/lib/supabase/realtime/socket.rb +40 -0
  50. data/lib/supabase/realtime/sockets/async_websocket.rb +175 -0
  51. data/lib/supabase/realtime/sockets/websocket_client_simple.rb +94 -0
  52. data/lib/supabase/realtime/test_socket.rb +65 -0
  53. data/lib/supabase/realtime/transformers.rb +26 -0
  54. data/lib/supabase/realtime/types.rb +70 -0
  55. data/lib/supabase/realtime/version.rb +7 -0
  56. data/lib/supabase/realtime.rb +18 -0
  57. data/lib/supabase/storage/README.md +108 -0
  58. data/lib/supabase/storage/analytics.rb +69 -0
  59. data/lib/supabase/storage/async/client.rb +52 -0
  60. data/lib/supabase/storage/async.rb +8 -0
  61. data/lib/supabase/storage/bucket_api.rb +65 -0
  62. data/lib/supabase/storage/client.rb +80 -0
  63. data/lib/supabase/storage/errors.rb +32 -0
  64. data/lib/supabase/storage/file_api.rb +281 -0
  65. data/lib/supabase/storage/request.rb +63 -0
  66. data/lib/supabase/storage/types.rb +236 -0
  67. data/lib/supabase/storage/utils.rb +35 -0
  68. data/lib/supabase/storage/vectors.rb +189 -0
  69. data/lib/supabase/storage/version.rb +7 -0
  70. data/lib/supabase/storage.rb +17 -0
  71. data/lib/supabase/version.rb +5 -0
  72. data/lib/supabase-auth.rb +3 -0
  73. data/lib/supabase.rb +63 -0
  74. metadata +272 -0
@@ -0,0 +1,517 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+
5
+ module Supabase
6
+ module Auth
7
+ module Types
8
+ # Parse an ISO8601 string into a Time object, or return nil
9
+ # @param value [String, Time, nil]
10
+ # @return [Time, nil]
11
+ def self.parse_timestamp(value)
12
+ return nil if value.nil?
13
+ return value if value.is_a?(Time)
14
+
15
+ Time.parse(value.to_s)
16
+ end
17
+
18
+ # Authentication method reference entry (matches Python AMREntry)
19
+ AMREntry = Struct.new(
20
+ :method,
21
+ :timestamp,
22
+ keyword_init: true
23
+ ) do
24
+ def self.from_hash(hash)
25
+ return nil if hash.nil?
26
+
27
+ new(
28
+ method: hash["method"] || hash[:method],
29
+ timestamp: hash["timestamp"] || hash[:timestamp]
30
+ )
31
+ end
32
+ end
33
+
34
+ Factor = Struct.new(
35
+ :id,
36
+ :friendly_name,
37
+ :factor_type,
38
+ :status,
39
+ :created_at,
40
+ :updated_at,
41
+ keyword_init: true
42
+ ) do
43
+ def self.from_hash(hash)
44
+ return nil if hash.nil?
45
+
46
+ new(
47
+ id: hash["id"] || hash[:id],
48
+ friendly_name: hash["friendly_name"] || hash[:friendly_name],
49
+ factor_type: hash["factor_type"] || hash[:factor_type],
50
+ status: hash["status"] || hash[:status],
51
+ created_at: Types.parse_timestamp(hash["created_at"] || hash[:created_at]),
52
+ updated_at: Types.parse_timestamp(hash["updated_at"] || hash[:updated_at])
53
+ )
54
+ end
55
+ end
56
+
57
+ Identity = Struct.new(
58
+ :id,
59
+ :identity_id,
60
+ :user_id,
61
+ :identity_data,
62
+ :provider,
63
+ :last_sign_in_at,
64
+ :created_at,
65
+ :updated_at,
66
+ keyword_init: true
67
+ ) do
68
+ def self.from_hash(hash)
69
+ return nil if hash.nil?
70
+
71
+ new(
72
+ id: hash["id"] || hash[:id],
73
+ identity_id: hash["identity_id"] || hash[:identity_id],
74
+ user_id: hash["user_id"] || hash[:user_id],
75
+ identity_data: hash["identity_data"] || hash[:identity_data] || {},
76
+ provider: hash["provider"] || hash[:provider],
77
+ last_sign_in_at: Types.parse_timestamp(hash["last_sign_in_at"] || hash[:last_sign_in_at]),
78
+ created_at: Types.parse_timestamp(hash["created_at"] || hash[:created_at]),
79
+ updated_at: Types.parse_timestamp(hash["updated_at"] || hash[:updated_at])
80
+ )
81
+ end
82
+ end
83
+
84
+ User = Struct.new(
85
+ :id,
86
+ :aud,
87
+ :role,
88
+ :email,
89
+ :email_confirmed_at,
90
+ :phone,
91
+ :phone_confirmed_at,
92
+ :confirmed_at,
93
+ :last_sign_in_at,
94
+ :app_metadata,
95
+ :user_metadata,
96
+ :identities,
97
+ :factors,
98
+ :created_at,
99
+ :updated_at,
100
+ :new_email,
101
+ :new_phone,
102
+ :invited_at,
103
+ :is_anonymous,
104
+ :is_sso_user,
105
+ :deleted_at,
106
+ :banned_until,
107
+ :confirmation_sent_at,
108
+ :recovery_sent_at,
109
+ :email_change_sent_at,
110
+ :action_link,
111
+ keyword_init: true
112
+ ) do
113
+ def self.from_hash(hash)
114
+ return nil if hash.nil?
115
+
116
+ identities = (hash["identities"] || hash[:identities])&.map { |i| Identity.from_hash(i) }
117
+ factors = (hash["factors"] || hash[:factors])&.map { |f| Factor.from_hash(f) }
118
+
119
+ new(
120
+ id: hash["id"] || hash[:id],
121
+ aud: hash["aud"] || hash[:aud],
122
+ role: hash["role"] || hash[:role],
123
+ email: hash["email"] || hash[:email],
124
+ email_confirmed_at: Types.parse_timestamp(hash["email_confirmed_at"] || hash[:email_confirmed_at]),
125
+ phone: hash["phone"] || hash[:phone],
126
+ phone_confirmed_at: Types.parse_timestamp(hash["phone_confirmed_at"] || hash[:phone_confirmed_at]),
127
+ confirmed_at: Types.parse_timestamp(hash["confirmed_at"] || hash[:confirmed_at]),
128
+ last_sign_in_at: Types.parse_timestamp(hash["last_sign_in_at"] || hash[:last_sign_in_at]),
129
+ app_metadata: hash["app_metadata"] || hash[:app_metadata] || {},
130
+ user_metadata: hash["user_metadata"] || hash[:user_metadata] || {},
131
+ identities: identities,
132
+ factors: factors,
133
+ created_at: Types.parse_timestamp(hash["created_at"] || hash[:created_at]),
134
+ updated_at: Types.parse_timestamp(hash["updated_at"] || hash[:updated_at]),
135
+ new_email: hash["new_email"] || hash[:new_email],
136
+ new_phone: hash["new_phone"] || hash[:new_phone],
137
+ invited_at: Types.parse_timestamp(hash["invited_at"] || hash[:invited_at]),
138
+ is_anonymous: hash.key?("is_anonymous") ? hash["is_anonymous"] : (hash.key?(:is_anonymous) ? hash[:is_anonymous] : false),
139
+ is_sso_user: hash.key?("is_sso_user") ? hash["is_sso_user"] : (hash.key?(:is_sso_user) ? hash[:is_sso_user] : false),
140
+ deleted_at: hash["deleted_at"] || hash[:deleted_at],
141
+ banned_until: hash["banned_until"] || hash[:banned_until],
142
+ confirmation_sent_at: Types.parse_timestamp(hash["confirmation_sent_at"] || hash[:confirmation_sent_at]),
143
+ recovery_sent_at: Types.parse_timestamp(hash["recovery_sent_at"] || hash[:recovery_sent_at]),
144
+ email_change_sent_at: Types.parse_timestamp(hash["email_change_sent_at"] || hash[:email_change_sent_at]),
145
+ action_link: hash["action_link"] || hash[:action_link]
146
+ )
147
+ end
148
+ end
149
+
150
+ Session = Struct.new(
151
+ :provider_token,
152
+ :provider_refresh_token,
153
+ :access_token,
154
+ :refresh_token,
155
+ :token_type,
156
+ :expires_in,
157
+ :expires_at,
158
+ :user,
159
+ keyword_init: true
160
+ ) do
161
+ def self.from_hash(hash)
162
+ return nil if hash.nil?
163
+
164
+ expires_at = hash["expires_at"] || hash[:expires_at]
165
+ expires_in = hash["expires_in"] || hash[:expires_in]
166
+ if expires_in && !expires_at
167
+ expires_at = Time.now.round.to_i + expires_in.to_i
168
+ end
169
+ expires_at = expires_at.to_i if expires_at
170
+
171
+ new(
172
+ provider_token: hash["provider_token"] || hash[:provider_token],
173
+ provider_refresh_token: hash["provider_refresh_token"] || hash[:provider_refresh_token],
174
+ access_token: hash["access_token"] || hash[:access_token],
175
+ refresh_token: hash["refresh_token"] || hash[:refresh_token],
176
+ token_type: hash["token_type"] || hash[:token_type],
177
+ expires_in: hash["expires_in"] || hash[:expires_in],
178
+ expires_at: expires_at,
179
+ user: User.from_hash(hash["user"] || hash[:user])
180
+ )
181
+ end
182
+ end
183
+
184
+ AuthResponse = Struct.new(
185
+ :user,
186
+ :session,
187
+ keyword_init: true
188
+ ) do
189
+ def self.from_hash(hash)
190
+ return nil if hash.nil?
191
+
192
+ new(
193
+ user: User.from_hash(hash["user"] || hash[:user]),
194
+ session: Session.from_hash(hash["session"] || hash[:session])
195
+ )
196
+ end
197
+ end
198
+
199
+ OAuthResponse = Struct.new(
200
+ :provider,
201
+ :url,
202
+ keyword_init: true
203
+ )
204
+
205
+ GenerateLinkProperties = Struct.new(
206
+ :action_link,
207
+ :email_otp,
208
+ :hashed_token,
209
+ :redirect_to,
210
+ :verification_type,
211
+ keyword_init: true
212
+ )
213
+
214
+ GenerateLinkResponse = Struct.new(
215
+ :properties,
216
+ :user,
217
+ keyword_init: true
218
+ )
219
+
220
+ UserResponse = Struct.new(
221
+ :user,
222
+ keyword_init: true
223
+ ) do
224
+ def self.from_hash(hash)
225
+ return nil if hash.nil?
226
+
227
+ new(user: User.from_hash(hash["user"] || hash[:user]))
228
+ end
229
+ end
230
+
231
+ SSOResponse = Struct.new(
232
+ :url,
233
+ keyword_init: true
234
+ ) do
235
+ def self.from_hash(hash)
236
+ return nil if hash.nil?
237
+
238
+ new(url: hash["url"] || hash[:url])
239
+ end
240
+ end
241
+
242
+ LinkIdentityResponse = Struct.new(
243
+ :url,
244
+ keyword_init: true
245
+ ) do
246
+ def self.from_hash(hash)
247
+ return nil if hash.nil?
248
+
249
+ new(url: hash["url"] || hash[:url])
250
+ end
251
+ end
252
+
253
+ AuthOtpResponse = Struct.new(
254
+ :message_id,
255
+ :user,
256
+ :session,
257
+ keyword_init: true
258
+ ) do
259
+ def self.from_hash(hash)
260
+ return nil if hash.nil?
261
+
262
+ new(
263
+ message_id: hash["message_id"] || hash[:message_id],
264
+ user: hash.key?("user") || hash.key?(:user) ? User.from_hash(hash["user"] || hash[:user]) : nil,
265
+ session: hash.key?("session") || hash.key?(:session) ? Session.from_hash(hash["session"] || hash[:session]) : nil
266
+ )
267
+ end
268
+ end
269
+ # MFA Enroll response - returned when enrolling a new TOTP factor
270
+ AuthMFAEnrollResponse = Struct.new(
271
+ :id,
272
+ :type,
273
+ :friendly_name,
274
+ :totp,
275
+ :phone,
276
+ keyword_init: true
277
+ ) do
278
+ def self.from_hash(hash)
279
+ return nil if hash.nil?
280
+
281
+ totp = hash["totp"] || hash[:totp]
282
+ totp_struct = totp ? MFATotpInfo.new(qr_code: totp["qr_code"] || totp[:qr_code],
283
+ secret: totp["secret"] || totp[:secret],
284
+ uri: totp["uri"] || totp[:uri]) : nil
285
+ new(
286
+ id: hash["id"] || hash[:id],
287
+ type: hash["type"] || hash[:type],
288
+ friendly_name: hash["friendly_name"] || hash[:friendly_name],
289
+ totp: totp_struct,
290
+ phone: hash["phone"] || hash[:phone]
291
+ )
292
+ end
293
+ end
294
+
295
+ AuthMFAEnrollResponseTotp = Struct.new(:qr_code, :secret, :uri, keyword_init: true)
296
+ MFATotpInfo = AuthMFAEnrollResponseTotp
297
+
298
+ # MFA Challenge response
299
+ AuthMFAChallengeResponse = Struct.new(
300
+ :id,
301
+ :factor_type,
302
+ :expires_at,
303
+ keyword_init: true
304
+ ) do
305
+ def self.from_hash(hash)
306
+ return nil if hash.nil?
307
+
308
+ new(
309
+ id: hash["id"] || hash[:id],
310
+ factor_type: hash["factor_type"] || hash[:factor_type] || hash["type"] || hash[:type],
311
+ expires_at: hash["expires_at"] || hash[:expires_at]
312
+ )
313
+ end
314
+ end
315
+
316
+ # MFA Unenroll response
317
+ AuthMFAUnenrollResponse = Struct.new(
318
+ :id,
319
+ keyword_init: true
320
+ ) do
321
+ def self.from_hash(hash)
322
+ return nil if hash.nil?
323
+
324
+ new(id: hash["id"] || hash[:id])
325
+ end
326
+ end
327
+
328
+ # MFA List Factors response
329
+ AuthMFAListFactorsResponse = Struct.new(
330
+ :all,
331
+ :totp,
332
+ :phone,
333
+ keyword_init: true
334
+ )
335
+
336
+ # MFA Verify response (matches Python: access_token, token_type, expires_in, refresh_token, user)
337
+ AuthMFAVerifyResponse = Struct.new(
338
+ :access_token,
339
+ :token_type,
340
+ :expires_in,
341
+ :refresh_token,
342
+ :user,
343
+ keyword_init: true
344
+ ) do
345
+ def self.from_hash(hash)
346
+ return nil if hash.nil?
347
+
348
+ new(
349
+ access_token: hash["access_token"] || hash[:access_token],
350
+ token_type: hash["token_type"] || hash[:token_type],
351
+ expires_in: hash["expires_in"] || hash[:expires_in],
352
+ refresh_token: hash["refresh_token"] || hash[:refresh_token],
353
+ user: User.from_hash(hash["user"] || hash[:user])
354
+ )
355
+ end
356
+ end
357
+
358
+ # MFA Get Authenticator Assurance Level response
359
+ AuthMFAGetAuthenticatorAssuranceLevelResponse = Struct.new(
360
+ :current_level,
361
+ :next_level,
362
+ :current_authentication_methods,
363
+ keyword_init: true
364
+ )
365
+
366
+ # Admin MFA List Factors response
367
+ AuthMFAAdminListFactorsResponse = Struct.new(
368
+ :factors,
369
+ keyword_init: true
370
+ ) do
371
+ def self.from_hash(hash)
372
+ return nil if hash.nil?
373
+
374
+ factors = (hash["factors"] || hash[:factors] || []).map { |f| Factor.from_hash(f) }
375
+ new(factors: factors)
376
+ end
377
+ end
378
+
379
+ # Admin MFA Delete Factor response
380
+ AuthMFAAdminDeleteFactorResponse = Struct.new(
381
+ :id,
382
+ keyword_init: true
383
+ ) do
384
+ def self.from_hash(hash)
385
+ return nil if hash.nil?
386
+
387
+ new(id: hash["id"] || hash[:id])
388
+ end
389
+ end
390
+
391
+ # Identities response (wraps user identities)
392
+ IdentitiesResponse = Struct.new(
393
+ :identities,
394
+ keyword_init: true
395
+ )
396
+
397
+ # User Identity (includes identity_id)
398
+ UserIdentity = Struct.new(
399
+ :id,
400
+ :identity_id,
401
+ :user_id,
402
+ :identity_data,
403
+ :provider,
404
+ :created_at,
405
+ :last_sign_in_at,
406
+ :updated_at,
407
+ keyword_init: true
408
+ ) do
409
+ def self.from_hash(hash)
410
+ return nil if hash.nil?
411
+
412
+ new(
413
+ id: hash["id"] || hash[:id],
414
+ identity_id: hash["identity_id"] || hash[:identity_id],
415
+ user_id: hash["user_id"] || hash[:user_id],
416
+ identity_data: hash["identity_data"] || hash[:identity_data] || {},
417
+ provider: hash["provider"] || hash[:provider],
418
+ created_at: Types.parse_timestamp(hash["created_at"] || hash[:created_at]),
419
+ last_sign_in_at: Types.parse_timestamp(hash["last_sign_in_at"] || hash[:last_sign_in_at]),
420
+ updated_at: Types.parse_timestamp(hash["updated_at"] || hash[:updated_at])
421
+ )
422
+ end
423
+ end
424
+
425
+ Subscription = Struct.new(
426
+ :id,
427
+ :callback,
428
+ :unsubscribe,
429
+ keyword_init: true
430
+ )
431
+
432
+ # JWT Claims response - returned by get_claims (matches Python ClaimsResponse)
433
+ ClaimsResponse = Struct.new(
434
+ :claims,
435
+ :headers,
436
+ :signature,
437
+ keyword_init: true
438
+ )
439
+
440
+ # OAuth 2.1 server: client object returned by admin OAuth endpoints.
441
+ OAuthClient = Struct.new(
442
+ :client_id,
443
+ :client_name,
444
+ :client_secret,
445
+ :client_type,
446
+ :token_endpoint_auth_method,
447
+ :registration_type,
448
+ :client_uri,
449
+ :logo_uri,
450
+ :redirect_uris,
451
+ :grant_types,
452
+ :response_types,
453
+ :scope,
454
+ :created_at,
455
+ :updated_at,
456
+ keyword_init: true
457
+ ) do
458
+ def self.from_hash(hash)
459
+ return nil if hash.nil?
460
+
461
+ new(
462
+ client_id: hash["client_id"] || hash[:client_id],
463
+ client_name: hash["client_name"] || hash[:client_name],
464
+ client_secret: hash["client_secret"] || hash[:client_secret],
465
+ client_type: hash["client_type"] || hash[:client_type],
466
+ token_endpoint_auth_method: hash["token_endpoint_auth_method"] || hash[:token_endpoint_auth_method],
467
+ registration_type: hash["registration_type"] || hash[:registration_type],
468
+ client_uri: hash["client_uri"] || hash[:client_uri],
469
+ logo_uri: hash["logo_uri"] || hash[:logo_uri],
470
+ redirect_uris: hash["redirect_uris"] || hash[:redirect_uris] || [],
471
+ grant_types: hash["grant_types"] || hash[:grant_types] || [],
472
+ response_types: hash["response_types"] || hash[:response_types] || [],
473
+ scope: hash["scope"] || hash[:scope],
474
+ created_at: hash["created_at"] || hash[:created_at],
475
+ updated_at: hash["updated_at"] || hash[:updated_at]
476
+ )
477
+ end
478
+ end
479
+
480
+ # OAuth 2.1 server: response wrapper for single-client operations.
481
+ OAuthClientResponse = Struct.new(
482
+ :client,
483
+ keyword_init: true
484
+ )
485
+
486
+ # OAuth 2.1 server: paginated list response.
487
+ OAuthClientListResponse = Struct.new(
488
+ :clients,
489
+ :aud,
490
+ :next_page,
491
+ :last_page,
492
+ :total,
493
+ keyword_init: true
494
+ ) do
495
+ def self.from_hash(hash)
496
+ return nil if hash.nil?
497
+
498
+ clients_data = hash["clients"] || hash[:clients] || []
499
+ new(
500
+ clients: clients_data.map { |c| OAuthClient.from_hash(c) },
501
+ aud: hash["aud"] || hash[:aud],
502
+ next_page: hash["next_page"] || hash[:next_page],
503
+ last_page: hash["last_page"] || hash[:last_page] || 0,
504
+ total: hash["total"] || hash[:total] || 0
505
+ )
506
+ end
507
+ end
508
+
509
+ # Pagination params accepted by admin list endpoints.
510
+ PageParams = Struct.new(
511
+ :page,
512
+ :per_page,
513
+ keyword_init: true
514
+ )
515
+ end
516
+ end
517
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Supabase
4
+ module Auth
5
+ VERSION = "0.2.0"
6
+ end
7
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "auth/version"
4
+ require_relative "auth/constants"
5
+ require_relative "auth/types"
6
+ require_relative "auth/errors"
7
+ require_relative "auth/api"
8
+ require_relative "auth/admin_api"
9
+ require_relative "auth/admin_oauth_api"
10
+ require_relative "auth/helpers"
11
+ require_relative "auth/storage"
12
+ require_relative "auth/memory_storage"
13
+ require_relative "auth/timer"
14
+ require_relative "auth/client"
15
+
16
+ module Supabase
17
+ module Auth
18
+ end
19
+ end