Skip to content

Update README, add docs #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 12, 2021
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
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,81 @@ Add `postgrest-swift` as a dependency to your `Package.swift` file. For more inf
.package(url: "https://github.com/supabase/postgrest-swift", from: "0.1.0")
```

### Supabase

You can also install the [ `supabase-swift`](https://github.com/supabase/supabase-swift) package to use the entire supabase library.

## Usage

Query todo table for all completed todos.
```swift
let client = PostgrestClient(url: "https://example.supabase.co", schema: nil)

do {
let query = try client.from("todos")
.select()
.eq(column: "isDone", value: "true")
try query.execute { [weak self] (results) in
guard let self = self else { return }

// Handle results
}
} catch {
print("Error querying for todos: \(error)")
}
```

Insert a todo into the database.
```swift
let client = PostgrestClient(url: "https://example.supabase.co", schema: nil)

struct Todo: Codable {
var id: UUID = UUID()
var label: String
var isDone: Bool = false
}

let todo = Todo(label: "Example todo!")

do {
let jsonData: Data = try JSONEncoder().encode(todo)
let jsonDict: [String: Any] = try JSONSerialization.jsonObject(with: jsonData, options: .allowFragments))

try client.from("todos")
.insert(values: jsonDict)
.execute { results in
// Handle response
}
} catch {
print("Error inserting the todo: \(error)")
}
```

For more query examples visit [the Javascript docs](https://supabase.io/docs/reference/javascript/select) to learn more. The API design is a near 1:1 match.

Execute an RPC
```swift
let client = PostgrestClient(url: "https://example.supabase.co", schema: nil)

do {
try client.rpc(fn: "testFunction", parameters: nil).execute { result in
// Handle result
}
} catch {
print("Error executing the RPC: \(error)")
}
```

## Auth

You can add authentication to the databases requests by using the `client.headers` property. For example to add a `Bearer` auth header, simply set the headers dictionary to:
```swift
let client = PostgrestClient(url: "https://example.supabase.co",
headers: ["Bearer": "{ Insert Token Here }"]
schema: nil)
```
All requests made using this client will be sent with the `Bearer Token` header.

## Contributing

- Fork the repo on GitHub
Expand Down
30 changes: 26 additions & 4 deletions Sources/PostgREST/PostgrestBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ public class PostgrestBuilder {
self.method = method
self.body = body
}


/// Executes the built query or command.
/// - Parameters:
/// - head: If `true` use `HEAD` for the HTTP method when building the URLRequest. Defaults to `true`
/// - 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.
public func execute(head: Bool = false, count: CountOption? = nil, completion: @escaping (Result<PostgrestResponse, Error>) -> Void) {
let request: URLRequest
do {
Expand Down Expand Up @@ -57,7 +62,12 @@ public class PostgrestBuilder {

dataTask.resume()
}


/// Validates the response from PostgREST
/// - Parameters:
/// - data: `Data` received from the server.
/// - 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 {
return
Expand All @@ -69,7 +79,13 @@ public class PostgrestBuilder {

throw PostgrestError(from: json) ?? PostgrestError(message: "failed to get error")
}


/// Parses incoming data and server response into a `PostgrestResponse`
/// - Parameters:
/// - data: Data received from the server
/// - response: Response received from the server
/// - Throws: Throws an `Error` if invalid JSON.
/// - Returns: Returns a `PostgrestResponse`
private static func parse(data: Data, response: HTTPURLResponse, request: URLRequest) throws -> PostgrestResponse {
var body: Any = data
var count: Int?
Expand All @@ -92,7 +108,13 @@ public class PostgrestBuilder {
postgrestResponse.count = count
return postgrestResponse
}


/// Builds the URL request for PostgREST
/// - Parameters:
/// - head: If on, use `HEAD` as the HTTP method.
/// - count: A `CountOption`,
/// - Throws: Throws a `PostgressError`
/// - Returns: Returns a valid URLRequest for the current query.
func buildURLRequest(head: Bool, count: CountOption?) throws -> URLRequest {
if head {
method = "HEAD"
Expand Down
24 changes: 21 additions & 3 deletions Sources/PostgREST/PostgrestClient.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,36 @@
/**
# PostgrestClient

This is the main class in this package. Use it to execute queries on a PostgREST instance on Supabase.
*/
public class PostgrestClient {
var url: String
var headers: [String: String]
var schema: String?


/// Initializes the `PostgrestClient` with the correct parameters.
/// - Parameters:
/// - url: Url of your supabase db instance
/// - headers: Headers to include when querying the database. Eg, an authentication header
/// - schema: Schema ID to use
public init(url: String, headers: [String: String] = [:], schema: String?) {
self.url = url
self.headers = headers
self.schema = schema
}


/// Select a table to query from
/// - Parameter table: The ID of the table to query
/// - Returns: `PostgrestQueryBuilder`
public func form(_ table: String) -> PostgrestQueryBuilder {
return PostgrestQueryBuilder(url: "\(url)/\(table)", queryParams: [], headers: headers, schema: schema, method: nil, body: nil)
}


/// Call a stored procedure, aka a "Remote Procedure Call"
/// - Parameters:
/// - fn: Procedure name to call.
/// - parameters: Parameters to pass to the procedure.
/// - Returns: `PostgrestTransformBuilder`
public func rpc(fn: String, parameters: [String: Any]?) -> PostgrestTransformBuilder {
return PostgrestRpcBuilder(url: "\(url)/rpc/\(fn)", queryParams: [], headers: headers, schema: schema, method: nil, body: nil).rpc(parameters: parameters)
}
Expand Down
3 changes: 1 addition & 2 deletions Tests/PostgRESTTests/BuildURLRequestTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ final class BuildURLRequestTests: XCTestCase {

for testCase in testCases {
let request = try testCase.build(client)
assertSnapshot(
matching: request, as: .curl, named: testCase.name, record: testCase.record)
assertSnapshot(matching: request, as: .curl, named: testCase.name, record: testCase.record)
}
}
}