Skip to content

Commit

Permalink
feat: expose PostgrestClient methods directly in SupabaseClient (#336)
Browse files Browse the repository at this point in the history
  • Loading branch information
grdsdev authored Apr 10, 2024
1 parent 1d7bad7 commit aca50a5
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 34 deletions.
10 changes: 10 additions & 0 deletions Sources/PostgREST/Deprecated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,13 @@ extension PostgrestClient {
)
}
}

extension PostgrestFilterBuilder {
@available(*, deprecated, renamed: "textSearch(_:value:)")
public func textSearch(
_ column: String,
range: any URLQueryRepresentable
) -> PostgrestFilterBuilder {
textSearch(column, value: range)
}
}
8 changes: 5 additions & 3 deletions Sources/PostgREST/PostgrestFilterBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -200,17 +200,19 @@ public class PostgrestFilterBuilder: PostgrestTransformBuilder {

public func textSearch(
_ column: String,
range: any URLQueryRepresentable
value: any URLQueryRepresentable
) -> PostgrestFilterBuilder {
let queryValue = range.queryValue
let queryValue = value.queryValue
mutableState.withValue {
$0.request.query.append(URLQueryItem(name: column, value: "adj.\(queryValue)"))
}
return self
}

public func textSearch(
_ column: String, query: any URLQueryRepresentable, config: String? = nil,
_ column: String,
query: any URLQueryRepresentable,
config: String? = nil,
type: TextSearchType? = nil
) -> PostgrestFilterBuilder {
let queryValue = query.queryValue
Expand Down
6 changes: 6 additions & 0 deletions Sources/Realtime/V2/RealtimeClientV2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ public actor RealtimeClientV2 {
}
}

public func removeAllChannels() async {
for channel in subscriptions.values {
await removeChannel(channel)
}
}

private func rejoinChannels() async {
for channel in subscriptions.values {
await channel.subscribe()
Expand Down
85 changes: 84 additions & 1 deletion Sources/Supabase/SupabaseClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,16 @@ public final class SupabaseClient: @unchecked Sendable {
public let auth: AuthClient

/// Database client for Supabase.
public private(set) lazy var database = PostgrestClient(
@available(
*,
deprecated,
message: "Direct access to database is deprecated, please use one of the available methods such as, SupabaseClient.from(_:), SupabaseClient.rpc(_:params:), or SupabaseClient.schema(_:)."
)
public var database: PostgrestClient {
rest
}

private lazy var rest = PostgrestClient(
url: databaseURL,
schema: options.db.schema,
headers: defaultHeaders,
Expand Down Expand Up @@ -145,6 +154,80 @@ public final class SupabaseClient: @unchecked Sendable {
listenForAuthEvents()
}

/// Performs a query on a table or a view.
/// - Parameter table: The table or view name to query.
/// - Returns: A PostgrestQueryBuilder instance.
public func from(_ table: String) -> PostgrestQueryBuilder {
rest.from(table)
}

/// Performs a function call.
/// - Parameters:
/// - fn: The function name to call.
/// - params: The parameters to pass to the function call.
/// - count: Count algorithm to use to count rows returned by the function.
/// Only applicable for set-returning functions.
/// - Returns: A PostgrestFilterBuilder instance.
/// - Throws: An error if the function call fails.
public func rpc(
_ fn: String,
params: some Encodable & Sendable,
count: CountOption? = nil
) throws -> PostgrestFilterBuilder {
try rest.rpc(fn, params: params, count: count)
}

/// Performs a function call.
/// - Parameters:
/// - fn: The function name to call.
/// - count: Count algorithm to use to count rows returned by the function.
/// Only applicable for set-returning functions.
/// - Returns: A PostgrestFilterBuilder instance.
/// - Throws: An error if the function call fails.
public func rpc(
_ fn: String,
count: CountOption? = nil
) throws -> PostgrestFilterBuilder {
try rest.rpc(fn, count: count)
}

/// Select a schema to query or perform an function (rpc) call.
///
/// The schema needs to be on the list of exposed schemas inside Supabase.
/// - Parameter schema: The schema to query.
public func schema(_ schema: String) -> PostgrestClient {
rest.schema(schema)
}

/// Returns all Realtime channels.
public var channels: [RealtimeChannelV2] {
get async {
await Array(realtimeV2.subscriptions.values)
}
}

/// Creates a Realtime channel with Broadcast, Presence, and Postgres Changes.
/// - Parameters:
/// - name: The name of the Realtime channel.
/// - options: The options to pass to the Realtime channel.
public func channel(
_ name: String,
options: @Sendable (inout RealtimeChannelConfig) -> Void = { _ in }
) async -> RealtimeChannelV2 {
await realtimeV2.channel(name, options: options)
}

/// Unsubscribes and removes Realtime channel from Realtime client.
/// - Parameter channel: The Realtime channel to remove.
public func removeChannel(_ channel: RealtimeChannelV2) async {
await realtimeV2.removeChannel(channel)
}

/// Unsubscribes and removes all Realtime channels from Realtime client.
public func removeAllChannels() async {
await realtimeV2.removeAllChannels()
}

deinit {
listenForAuthEventsTask.value?.cancel()
}
Expand Down
61 changes: 31 additions & 30 deletions Tests/RealtimeTests/_PushTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,34 +47,35 @@ final class _PushTests: XCTestCase {
XCTAssertEqual(status, .ok)
}

func testPushWithAck() async {
let channel = RealtimeChannelV2(
topic: "realtime:users",
config: RealtimeChannelConfig(
broadcast: .init(acknowledgeBroadcasts: true),
presence: .init()
),
socket: socket,
logger: nil
)
let push = PushV2(
channel: channel,
message: RealtimeMessageV2(
joinRef: nil,
ref: "1",
topic: "realtime:users",
event: "broadcast",
payload: [:]
)
)

let task = Task {
await push.send()
}
await Task.megaYield()
await push.didReceive(status: .ok)

let status = await task.value
XCTAssertEqual(status, .ok)
}
// FIXME: Flaky test, it fails some time due the task scheduling, even tho we're using withMainSerialExecutor.
// func testPushWithAck() async {
// let channel = RealtimeChannelV2(
// topic: "realtime:users",
// config: RealtimeChannelConfig(
// broadcast: .init(acknowledgeBroadcasts: true),
// presence: .init()
// ),
// socket: socket,
// logger: nil
// )
// let push = PushV2(
// channel: channel,
// message: RealtimeMessageV2(
// joinRef: nil,
// ref: "1",
// topic: "realtime:users",
// event: "broadcast",
// payload: [:]
// )
// )
//
// let task = Task {
// await push.send()
// }
// await Task.megaYield()
// await push.didReceive(status: .ok)
//
// let status = await task.value
// XCTAssertEqual(status, .ok)
// }
}

0 comments on commit aca50a5

Please sign in to comment.