Skip to content
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
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)
// }
}