Skip to content

Commit

Permalink
Merge pull request #51 from appwrite/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
abnegate authored Mar 8, 2024
2 parents d19fb1f + 799f169 commit c39030d
Show file tree
Hide file tree
Showing 115 changed files with 2,812 additions and 603 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2023 Appwrite (https://appwrite.io) and individual contributors.
Copyright (c) 2024 Appwrite (https://appwrite.io) and individual contributors.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Expand Down
13 changes: 11 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@ let package = Package(
products: [
.library(
name: "Appwrite",
targets: ["Appwrite", "AppwriteModels", "JSONCodable"]
targets: [
"Appwrite",
"AppwriteEnums",
"AppwriteModels",
"JSONCodable"
]
),
],
dependencies: [
.package(url: "https://github.com/swift-server/async-http-client.git", from: "1.9.0"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.32.0")
.package(url: "https://github.com/apple/swift-nio.git", from: "2.32.0"),
],
targets: [
.target(
Expand All @@ -27,6 +32,7 @@ let package = Package(
.product(name: "AsyncHTTPClient", package: "async-http-client"),
.product(name: "NIOWebSocket", package: "swift-nio"),
"AppwriteModels",
"AppwriteEnums",
"JSONCodable"
]
),
Expand All @@ -36,6 +42,9 @@ let package = Package(
"JSONCodable"
]
),
.target(
name: "AppwriteEnums"
),
.target(
name: "JSONCodable"
),
Expand Down
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

![Swift Package Manager](https://img.shields.io/github/v/release/appwrite/sdk-for-apple.svg?color=green&style=flat-square)
![License](https://img.shields.io/github/license/appwrite/sdk-for-apple.svg?style=flat-square)
![Version](https://img.shields.io/badge/api%20version-1.4.12-blue.svg?style=flat-square)
![Version](https://img.shields.io/badge/api%20version-1.5.0-blue.svg?style=flat-square)
[![Build Status](https://img.shields.io/travis/com/appwrite/sdk-generator?style=flat-square)](https://travis-ci.com/appwrite/sdk-generator)
[![Twitter Account](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite)
[![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord)

**This SDK is compatible with Appwrite server version 1.4.x. For older versions, please check [previous releases](https://github.com/appwrite/sdk-for-apple/releases).**
**This SDK is compatible with Appwrite server version 1.5.x. For older versions, please check [previous releases](https://github.com/appwrite/sdk-for-apple/releases).**

Appwrite is an open-source backend as a service server that abstract and simplify complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the Apple SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)

![Appwrite](https://appwrite.io/images/github.png)
![Appwrite](https://github.com/appwrite/appwrite/raw/main/public/images/github.png)

## Installation

Expand All @@ -31,7 +31,7 @@ Add the package to your `Package.swift` dependencies:

```swift
dependencies: [
.package(url: "[email protected]:appwrite/sdk-for-apple.git", from: "4.0.2"),
.package(url: "[email protected]:appwrite/sdk-for-apple.git", from: "5.0.0"),
],
```

Expand Down Expand Up @@ -125,9 +125,10 @@ let account = Account(client)

do {
let user = try await account.create(
userId: ID.unique(),
email: "[email protected]",
password: "password"
userId: ID.unique(),
email: "[email protected]",
password: "password",
name: "Walter O'Brien"
)
print(String(describing: user.toMap()))
} catch {
Expand All @@ -150,9 +151,10 @@ func main() {

do {
let user = try await account.create(
userId: ID.unique(),
email: "[email protected]",
password: "password"
userId: ID.unique(),
email: "[email protected]",
password: "password",
name: "Walter O'Brien"
)
print(String(describing: account.toMap()))
} catch {
Expand Down
157 changes: 72 additions & 85 deletions Sources/Appwrite/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,31 @@ open class Client {
// MARK: Properties
public static var chunkSize = 5 * 1024 * 1024 // 5MB

open var endPoint = "https://HOSTNAME/v1"
open var endPoint = "https://cloud.appwrite.io/v1"

open var endPointRealtime: String? = nil

open var headers: [String: String] = [
"content-type": "",
"content-type": "application/json",
"x-sdk-name": "Apple",
"x-sdk-platform": "client",
"x-sdk-language": "apple",
"x-sdk-version": "4.0.2",
"X-Appwrite-Response-Format": "1.4.0"
"x-sdk-version": "5.0.0",
"x-appwrite-response-format": "1.5.0"
]

open var config: [String: String] = [:]
internal var config: [String: String] = [:]

open var selfSigned: Bool = false
internal var selfSigned: Bool = false

open var http: HTTPClient
internal var http: HTTPClient

private static let boundaryChars =
"abcdefghijklmnopqrstuvwxyz1234567890"

private static let boundaryChars = "abcdefghijklmnopqrstuvwxyz1234567890"

private static let boundary = randomBoundary()

private static var eventLoopGroupProvider =
HTTPClient.EventLoopGroupProvider.createNew
private static var eventLoopGroupProvider = HTTPClient.EventLoopGroupProvider.singleton

// MARK: Methods

Expand Down Expand Up @@ -80,7 +79,6 @@ open class Client {
decompression: .enabled(limit: .none)
)
)

}

deinit {
Expand Down Expand Up @@ -134,6 +132,21 @@ open class Client {
return self
}

///
/// Set Session
///
/// The user session to authenticate with
///
/// @param String value
///
/// @return Client
///
open func setSession(_ value: String) -> Client {
config["session"] = value
_ = addHeader(key: "X-Appwrite-Session", value: value)
return self
}


///
/// Set self signed
Expand Down Expand Up @@ -295,64 +308,54 @@ open class Client {
withSink bufferSink: ((ByteBuffer) -> Void)? = nil,
converter: ((Any) -> T)? = nil
) async throws -> T {
func complete(with response: HTTPClientResponse) async throws -> T {
switch response.status.code {
case 0..<400:
if response.headers["Set-Cookie"].count > 0 {
UserDefaults.standard.set(
response.headers["Set-Cookie"],
forKey: URL(string: request.url)!.host! + "-cookies"
)
}
switch T.self {
case is Bool.Type:
return true as! T
case is ByteBuffer.Type:
return try await response.body.collect(upTo: Int.max) as! T
default:
let data = try await response.body.collect(upTo: Int.max)
if data.readableBytes == 0 {
return true as! T
}
let dict = try JSONSerialization.jsonObject(with: data) as? [String: Any]
let response = try await http.execute(
request,
timeout: .seconds(30)
)

return converter?(dict!) ?? dict! as! T
}
switch response.status.code {
case 0..<400:
if response.headers["Set-Cookie"].count > 0 {
let domain = URL(string: request.url)!.host!
let existing = UserDefaults.standard.stringArray(forKey: domain)
let new = response.headers["Set-Cookie"]

UserDefaults.standard.set(new, forKey: domain)
}
switch T.self {
case is Bool.Type:
return true as! T
case is ByteBuffer.Type:
return try await response.body.collect(upTo: Int.max) as! T
default:
var message = ""
var data = try await response.body.collect(upTo: Int.max)
var type = ""

do {
let dict = try JSONSerialization.jsonObject(with: data) as? [String: Any]

message = dict?["message"] as? String ?? response.status.reasonPhrase
type = dict?["type"] as? String ?? ""
} catch {
message = data.readString(length: data.readableBytes)!
let data = try await response.body.collect(upTo: Int.max)
if data.readableBytes == 0 {
return true as! T
}
let dict = try JSONSerialization.jsonObject(with: data) as? [String: Any]

throw AppwriteError(
message: message,
code: Int(response.status.code),
type: type
)
return converter?(dict!) ?? dict! as! T
}
}
default:
var message = ""
var data = try await response.body.collect(upTo: Int.max)
var type = ""

do {
let dict = try JSONSerialization.jsonObject(with: data) as? [String: Any]

if bufferSink == nil {
let response = try await http.execute(
request,
timeout: .seconds(30)
message = dict?["message"] as? String ?? response.status.reasonPhrase
type = dict?["type"] as? String ?? ""
} catch {
message = data.readString(length: data.readableBytes)!
}

throw AppwriteError(
message: message,
code: Int(response.status.code),
type: type
)
return try await complete(with: response)
}

let response = try await http.execute(
request,
timeout: .seconds(30)
)
return try await complete(with: response)
}

func chunkedUpload<T>(
Expand Down Expand Up @@ -411,7 +414,7 @@ open class Client {
while offset < size {
let slice = (input.data as! ByteBuffer).getSlice(at: offset, length: Client.chunkSize)
?? (input.data as! ByteBuffer).getSlice(at: offset, length: Int(size - offset))

params[paramName] = InputFile.fromBuffer(slice!, filename: input.filename, mimeType: input.mimeType)
headers["content-range"] = "bytes \(offset)-\(min((offset + Client.chunkSize) - 1, size - 1))/\(size)"

Expand Down Expand Up @@ -466,7 +469,12 @@ open class Client {
|| param is [Bool: Any] {
encodedParams[key] = param
} else {
encodedParams[key] = try! (param as! Encodable).toJson()
let value = try! (param as! Encodable).toJson()

let range = value.index(value.startIndex, offsetBy: 1)..<value.index(value.endIndex, offsetBy: -1)
let substring = value[range]

encodedParams[key] = substring
}
}

Expand Down Expand Up @@ -603,24 +611,3 @@ extension Client {
return device
}
}

extension Client {

public enum HTTPStatus: Int {
case unknown = -1
case ok = 200
case created = 201
case accepted = 202
case movedPermanently = 301
case found = 302
case badRequest = 400
case notAuthorized = 401
case paymentRequired = 402
case forbidden = 403
case notFound = 404
case methodNotAllowed = 405
case notAcceptable = 406
case internalServerError = 500
case notImplemented = 501
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extension HTTPClientRequest {

extension HTTPHeaders {
public mutating func addDomainCookies(for domain: String) {
guard let cookies = UserDefaults.standard.stringArray(forKey: "\(domain)-cookies") else {
guard let cookies = UserDefaults.standard.stringArray(forKey: domain) else {
return
}
for cookie in cookies {
Expand Down
5 changes: 4 additions & 1 deletion Sources/Appwrite/OAuth/WebAuthComponent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ public class WebAuthComponent {
cookie += "; secure"
}

UserDefaults.standard.set([cookie], forKey: "\(domain)-cookies")
let existing = UserDefaults.standard.stringArray(forKey: domain)
let new = [cookie]

UserDefaults.standard.set(new, forKey: domain)

WebAuthComponent.onCallback(
scheme: components.scheme!,
Expand Down
Loading

0 comments on commit c39030d

Please sign in to comment.