Skip to content

Commit

Permalink
refactor: make PostgrestClient a class and not an actor (#282)
Browse files Browse the repository at this point in the history
  • Loading branch information
grdsdev authored Mar 27, 2024
1 parent f167264 commit a701bb1
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 29 deletions.
2 changes: 1 addition & 1 deletion Sources/PostgREST/Deprecated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ extension PostgrestClient {
deprecated,
message: "Replace usages of this initializer with new init(url:schema:headers:logger:fetch:encoder:decoder:)"
)
public init(
public convenience init(
url: URL,
schema: String? = nil,
headers: [String: String] = [:],
Expand Down
19 changes: 11 additions & 8 deletions Sources/PostgREST/PostgrestClient.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation
@_spi(Internal) import _Helpers
import ConcurrencyExtras

public typealias PostgrestError = _Helpers.PostgrestError

Expand All @@ -8,7 +9,7 @@ public typealias PostgrestError = _Helpers.PostgrestError
#endif

/// PostgREST client.
public actor PostgrestClient {
public final class PostgrestClient: Sendable {
public typealias FetchHandler = @Sendable (_ request: URLRequest) async throws -> (
Data, URLResponse
)
Expand Down Expand Up @@ -52,14 +53,16 @@ public actor PostgrestClient {
}
}

public private(set) var configuration: Configuration
let _configuration: LockIsolated<Configuration>
public var configuration: Configuration { _configuration.value }

/// Creates a PostgREST client with the specified configuration.
/// - Parameter configuration: The configuration for the client.
public init(configuration: Configuration) {
var configuration = configuration
configuration.headers.merge(Configuration.defaultHeaders) { l, _ in l }
self.configuration = configuration
_configuration = LockIsolated(configuration)
_configuration.withValue {
$0.headers.merge(Configuration.defaultHeaders) { l, _ in l }
}
}

/// Creates a PostgREST client with the specified parameters.
Expand All @@ -71,7 +74,7 @@ public actor PostgrestClient {
/// - session: The URLSession to use for requests.
/// - encoder: The JSONEncoder to use for encoding.
/// - decoder: The JSONDecoder to use for decoding.
public init(
public convenience init(
url: URL,
schema: String? = nil,
headers: [String: String] = [:],
Expand Down Expand Up @@ -99,9 +102,9 @@ public actor PostgrestClient {
@discardableResult
public func setAuth(_ token: String?) -> PostgrestClient {
if let token {
configuration.headers["Authorization"] = "Bearer \(token)"
_configuration.withValue { $0.headers["Authorization"] = "Bearer \(token)" }
} else {
configuration.headers.removeValue(forKey: "Authorization")
_ = _configuration.withValue { $0.headers.removeValue(forKey: "Authorization") }
}
return self
}
Expand Down
40 changes: 20 additions & 20 deletions Tests/PostgRESTTests/BuildURLRequestTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,16 @@ final class BuildURLRequestTests: XCTestCase {

let testCases: [TestCase] = [
TestCase(name: "select all users where email ends with '@supabase.co'") { client in
await client.from("users")
client.from("users")
.select()
.like("email", value: "%@supabase.co")
},
TestCase(name: "insert new user") { client in
try await client.from("users")
try client.from("users")
.insert(User(email: "[email protected]"))
},
TestCase(name: "bulk insert users") { client in
try await client.from("users")
try client.from("users")
.insert(
[
User(email: "[email protected]"),
Expand All @@ -95,16 +95,16 @@ final class BuildURLRequestTests: XCTestCase {
)
},
TestCase(name: "call rpc") { client in
try await client.rpc("test_fcn", params: ["KEY": "VALUE"])
try client.rpc("test_fcn", params: ["KEY": "VALUE"])
},
TestCase(name: "call rpc without parameter") { client in
try await client.rpc("test_fcn")
try client.rpc("test_fcn")
},
TestCase(name: "call rpc with filter") { client in
try await client.rpc("test_fcn").eq("id", value: 1)
try client.rpc("test_fcn").eq("id", value: 1)
},
TestCase(name: "test all filters and count") { client in
var query = await client.from("todos").select()
var query = client.from("todos").select()

for op in PostgrestFilterBuilder.Operator.allCases {
query = query.filter("column", operator: op, value: "Some value")
Expand All @@ -113,28 +113,28 @@ final class BuildURLRequestTests: XCTestCase {
return query
},
TestCase(name: "test in filter") { client in
await client.from("todos").select().in("id", value: [1, 2, 3])
client.from("todos").select().in("id", value: [1, 2, 3])
},
TestCase(name: "test contains filter with dictionary") { client in
await client.from("users").select("name")
client.from("users").select("name")
.contains("address", value: ["postcode": 90210])
},
TestCase(name: "test contains filter with array") { client in
await client.from("users")
client.from("users")
.select()
.contains("name", value: ["is:online", "faction:red"])
},
TestCase(name: "test or filter with referenced table") { client in
await client.from("users")
client.from("users")
.select("*, messages(*)")
.or("public.eq.true,recipient_id.eq.1", referencedTable: "messages")
},
TestCase(name: "test upsert not ignoring duplicates") { client in
try await client.from("users")
try client.from("users")
.upsert(User(email: "[email protected]"))
},
TestCase(name: "bulk upsert") { client in
try await client.from("users")
try client.from("users")
.upsert(
[
User(email: "[email protected]"),
Expand All @@ -143,27 +143,27 @@ final class BuildURLRequestTests: XCTestCase {
)
},
TestCase(name: "test upsert ignoring duplicates") { client in
try await client.from("users")
try client.from("users")
.upsert(User(email: "[email protected]"), ignoreDuplicates: true)
},
TestCase(name: "query with + character") { client in
await client.from("users")
client.from("users")
.select()
.eq("id", value: "Cigányka-ér (0+400 cskm) vízrajzi állomás")
},
TestCase(name: "query with timestampz") { client in
await client.from("tasks")
client.from("tasks")
.select()
.gt("received_at", value: "2023-03-23T15:50:30.511743+00:00")
.order("received_at")
},
TestCase(name: "query non-default schema") { client in
await client.schema("storage")
client.schema("storage")
.from("objects")
.select()
},
TestCase(name: "select after an insert") { client in
try await client.from("users")
try client.from("users")
.insert(User(email: "[email protected]"))
.select("id,email")
},
Expand All @@ -176,9 +176,9 @@ final class BuildURLRequestTests: XCTestCase {
}
}

func testSessionConfiguration() async {
func testSessionConfiguration() {
let client = PostgrestClient(url: url, schema: nil, logger: nil)
let clientInfoHeader = await client.configuration.headers["X-Client-Info"]
let clientInfoHeader = client.configuration.headers["X-Client-Info"]
XCTAssertNotNil(clientInfoHeader)
}
}
Expand Down

0 comments on commit a701bb1

Please sign in to comment.