Skip to content

Commit

Permalink
Add PostgrestHTTPClient and remove non-concurrency method versions (s…
Browse files Browse the repository at this point in the history
…upabase-community#33)

* Add PostgrestHTTPClient

* Make default http client public

* Format
  • Loading branch information
grdsdev authored Oct 21, 2022
1 parent 606d23a commit bdfefac
Show file tree
Hide file tree
Showing 13 changed files with 89 additions and 129 deletions.
17 changes: 9 additions & 8 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
// swift-tools-version:5.3
// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "PostgREST",
platforms: [
.iOS(.v11),
.macOS(.v10_10),
.watchOS(.v3),
.tvOS(.v10),
.iOS(.v13),
.macCatalyst(.v13),
.macOS(.v10_15),
.watchOS(.v6),
.tvOS(.v13),
],
products: [
.library(
name: "PostgREST",
targets: ["PostgREST"]
)
),
],
dependencies: [
.package(
Expand All @@ -28,7 +29,7 @@ let package = Package(
.target(
name: "PostgREST",
dependencies: [
"AnyCodable"
"AnyCodable",
]
),
.testTarget(
Expand All @@ -42,7 +43,7 @@ let package = Package(
),
],
exclude: [
"__Snapshots__"
"__Snapshots__",
]
),
.testTarget(name: "PostgRESTIntegrationTests", dependencies: ["PostgREST"]),
Expand Down
17 changes: 0 additions & 17 deletions Sources/PostgREST/Concurrency.swift

This file was deleted.

2 changes: 1 addition & 1 deletion Sources/PostgREST/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ import Foundation

enum Constants {
static let defaultHeaders = [
"X-Client-Info": "postgrest-swift/\(version)"
"X-Client-Info": "postgrest-swift/\(version)",
]
}
77 changes: 17 additions & 60 deletions Sources/PostgREST/PostgrestBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class PostgrestBuilder {
var schema: String?
var method: String?
var body: AnyEncodable?
var delegate: PostgrestClientDelegate
var http: PostgrestHTTPClient

init(
client: PostgrestClient,
Expand All @@ -23,7 +23,7 @@ public class PostgrestBuilder {
schema: String?,
method: String?,
body: AnyEncodable?,
delegate: PostgrestClientDelegate
http: PostgrestHTTPClient
) {
self.client = client
self.url = url
Expand All @@ -32,7 +32,7 @@ public class PostgrestBuilder {
self.schema = schema
self.method = method
self.body = body
self.delegate = delegate
self.http = http
}

convenience init(_ other: PostgrestBuilder) {
Expand All @@ -44,42 +44,27 @@ public class PostgrestBuilder {
schema: other.schema,
method: other.method,
body: other.body,
delegate: other.delegate
http: other.http
)
}

/// Executes the built query or command.
/// - Parameters:
/// - head: If `true` use `HEAD` for the HTTP method when building the URLRequest. Defaults to `false`
/// - head: If `true` use `HEAD` for the HTTP method when building the URLRequest. Defaults to
/// `false`
/// - count: A `CountOption` determining how many items to return. Defaults to `nil`
/// - completion: Escaping completion handler with either a `PostgrestResponse` or an `Error`. Called after API call is completed and validated.
/// - completion: Escaping completion handler with either a `PostgrestResponse` or an `Error`.
/// Called after API call is completed and validated.
@discardableResult
public func execute(
head: Bool = false,
count: CountOption? = nil,
completion: @escaping (Result<PostgrestResponse, Error>) -> Void
) {
do {
let request = try buildURLRequest(head: head, count: count)

delegate.client(client, willSendRequest: request) { request in
URLSession.shared.fetch(request) { result in
switch result {
case .failure(let error):
completion(.failure(error))
case let .success((data, response)):
do {
try Self.validate(data: data, response: response)
let response = PostgrestResponse(data: data, response: response)
completion(.success(response))
} catch {
completion(.failure(error))
}
}
}
}
} catch {
completion(.failure(error))
}
count: CountOption? = nil
) async throws -> PostgrestResponse {
let request = try buildURLRequest(head: head, count: count)

let (data, response) = try await http.execute(request)
try Self.validate(data: data, response: response)
return PostgrestResponse(data: data, response: response)
}

/// Validates the response from PostgREST
Expand All @@ -88,7 +73,7 @@ public class PostgrestBuilder {
/// - response: `HTTPURLResponse` received from the server.
/// - Throws: Throws `PostgrestError` if invalid JSON object.
private static func validate(data: Data, response: HTTPURLResponse) throws {
if 200..<300 ~= response.statusCode {
if 200 ..< 300 ~= response.statusCode {
return
}

Expand Down Expand Up @@ -171,31 +156,3 @@ extension JSONEncoder {
return encoder
}()
}

extension URLSession {
func fetch(
_ request: URLRequest,
completion: @escaping (Result<(Data, HTTPURLResponse), Error>) -> Void
) {
let dataTask = dataTask(with: request) { data, response, error in
if let error = error {
completion(.failure(error))
return
}

guard let httpResponse = response as? HTTPURLResponse else {
completion(.failure(URLError(.badServerResponse)))
return
}

guard let data = data else {
completion(.failure(URLError(.badServerResponse)))
return
}

completion(.success((data, httpResponse)))
}

dataTask.resume()
}
}
39 changes: 10 additions & 29 deletions Sources/PostgREST/PostgrestClient.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation

/// This is the main class in this package. Use it to execute queries on a PostgREST instance on Supabase.
/// This is the main class in this package. Use it to execute queries on a PostgREST instance on
/// Supabase.
public class PostgrestClient {
/// Configuration for the client
public var config: PostgrestClientConfig
Expand All @@ -10,18 +11,18 @@ public class PostgrestClient {
public var url: String
public var headers: [String: String]
public var schema: String?
public var delegate: PostgrestClientDelegate
public var http: PostgrestHTTPClient

public init(
url: String,
headers: [String: String] = [:],
schema: String?,
delegate: PostgrestClientDelegate? = nil
http: PostgrestHTTPClient? = nil
) {
self.url = url
self.headers = headers.merging(Constants.defaultHeaders) { old, _ in old }
self.schema = schema
self.delegate = delegate ?? DefaultPostgrestClientDelegate()
self.http = http ?? DefaultPostgrestHTTPClient()
}
}

Expand All @@ -34,13 +35,13 @@ public class PostgrestClient {
url: String,
headers: [String: String] = [:],
schema: String?,
delegate: PostgrestClientDelegate? = nil
http: PostgrestHTTPClient? = nil
) {
self.config = PostgrestClientConfig(
config = PostgrestClientConfig(
url: url,
headers: headers,
schema: schema,
delegate: delegate
http: http
)
}

Expand Down Expand Up @@ -68,7 +69,7 @@ public class PostgrestClient {
schema: config.schema,
method: nil,
body: nil,
delegate: config.delegate
http: config.http
)
}

Expand All @@ -88,7 +89,7 @@ public class PostgrestClient {
schema: config.schema,
method: nil,
body: nil,
delegate: config.delegate
http: config.http
).rpc(params: params, count: count)
}

Expand All @@ -103,23 +104,3 @@ public class PostgrestClient {
rpc(fn: fn, params: EmptyParams(), count: count)
}
}

public protocol PostgrestClientDelegate {
func client(
_ client: PostgrestClient,
willSendRequest request: URLRequest,
completion: @escaping (URLRequest) -> Void
)
}

extension PostgrestClientDelegate {
public func client(
_ client: PostgrestClient,
willSendRequest request: URLRequest,
completion: @escaping (URLRequest) -> Void
) {
completion(request)
}
}

struct DefaultPostgrestClientDelegate: PostgrestClientDelegate {}
7 changes: 5 additions & 2 deletions Sources/PostgREST/PostgrestFilterBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Foundation
public class PostgrestFilterBuilder: PostgrestTransformBuilder {
public enum Operator: String, CaseIterable {
case eq, neq, gt, gte, lt, lte, like, ilike, `is`, `in`, cs, cd, sl, sr, nxl, nxr, adj, ov, fts,
plfts, phfts, wfts
plfts, phfts, wfts
}

// MARK: - Filters
Expand Down Expand Up @@ -66,7 +66,10 @@ public class PostgrestFilterBuilder: PostgrestTransformBuilder {
}

public func `in`(column: String, value: [URLQueryRepresentable]) -> PostgrestFilterBuilder {
appendSearchParams(name: column, value: "in.(\(value.map(\.queryValue).joined(separator: ",")))")
appendSearchParams(
name: column,
value: "in.(\(value.map(\.queryValue).joined(separator: ",")))"
)
return self
}

Expand Down
32 changes: 32 additions & 0 deletions Sources/PostgREST/PostgrestHTTPClient.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import Foundation

public protocol PostgrestHTTPClient {
func execute(_ request: URLRequest) async throws -> (Data, HTTPURLResponse)
}

public struct DefaultPostgrestHTTPClient: PostgrestHTTPClient {
public init() {}

public func execute(_ request: URLRequest) async throws -> (Data, HTTPURLResponse) {
try await withCheckedThrowingContinuation { continuation in
let dataTask = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
continuation.resume(throwing: error)
return
}

guard
let data = data,
let httpResponse = response as? HTTPURLResponse
else {
continuation.resume(throwing: URLError(.badServerResponse))
return
}

continuation.resume(returning: (data, httpResponse))
}

dataTask.resume()
}
}
}
12 changes: 8 additions & 4 deletions Sources/PostgREST/PostgrestQueryBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ public final class PostgrestQueryBuilder: PostgrestBuilder {
/// Performs an UPSERT into the table.
/// - Parameters:
/// - values: The values to insert.
/// - onConflict: By specifying the `on_conflict` query parameter, you can make UPSERT work on a column(s) that has a unique constraint.
/// - returning: By default the new record is returned. Set this to `minimal` if you don't need this value.
/// - onConflict: By specifying the `on_conflict` query parameter, you can make UPSERT work on a
/// column(s) that has a unique constraint.
/// - returning: By default the new record is returned. Set this to `minimal` if you don't need
/// this value.
/// - count: Count algorithm to use to count rows in a table.
/// - ignoreDuplicates: Specifies if duplicate rows should be ignored and not inserted.
public func upsert<U: Encodable>(
Expand Down Expand Up @@ -106,7 +108,8 @@ public final class PostgrestQueryBuilder: PostgrestBuilder {
/// Performs an UPDATE on the table.
/// - Parameters:
/// - values: The values to update.
/// - returning: By default the updated record is returned. Set this to `minimal` if you don't need this value.
/// - returning: By default the updated record is returned. Set this to `minimal` if you don't
/// need this value.
/// - count: Count algorithm to use to count rows in a table.
public func update<U: Encodable>(
values: U,
Expand All @@ -130,7 +133,8 @@ public final class PostgrestQueryBuilder: PostgrestBuilder {

/// Performs a DELETE on the table.
/// - Parameters:
/// - returning: By default the deleted rows are returned. Set this to `minimal` if you don't need this value.
/// - returning: By default the deleted rows are returned. Set this to `minimal` if you don't
/// need this value.
/// - count: Count algorithm to use to count rows in a table.
public func delete(
returning: PostgrestReturningOptions = .representation,
Expand Down
3 changes: 1 addition & 2 deletions Sources/PostgREST/PostgrestResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public struct PostgrestResponse: Hashable {
var count: Int?

if let contentRange = response.allHeaderFields["content-range"] as? String,
let lastElement = contentRange.split(separator: "/").last
let lastElement = contentRange.split(separator: "/").last
{
count = lastElement == "*" ? nil : Int(lastElement)
}
Expand All @@ -29,7 +29,6 @@ public struct PostgrestResponse: Hashable {
}

extension PostgrestResponse {

public func json() throws -> Any {
try JSONSerialization.jsonObject(with: data, options: [.allowFragments])
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/PostgREST/PostgrestReturningOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
///
/// https://postgrest.org/en/v9.0/api.html?highlight=PREFER#insertions-updates
public enum PostgrestReturningOptions: String {
case minimal = "minimal"
case representation = "representation"
case minimal
case representation
}
Loading

0 comments on commit bdfefac

Please sign in to comment.