Skip to content

Commit

Permalink
feat: realtime + pencilkit sample
Browse files Browse the repository at this point in the history
  • Loading branch information
drochetti committed Nov 28, 2023
1 parent 0b7c6b4 commit a46ba25
Show file tree
Hide file tree
Showing 19 changed files with 642 additions and 143 deletions.
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/nicklockwood/SwiftFormat",
"state" : {
"revision" : "d37a477177d5d4ff2a3ae6328eaaab5bf793e702",
"version" : "0.52.9"
"revision" : "cac06079ce883170ab44cb021faad298daeec2a5",
"version" : "0.52.10"
}
}
],
Expand Down
20 changes: 14 additions & 6 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import PackageDescription
let package = Package(
name: "FalClient",
platforms: [
.iOS(.v13),
.macOS(.v11),
.iOS(.v15),
.macOS(.v12),
.macCatalyst(.v13),
.tvOS(.v13),
.watchOS(.v8),
Expand All @@ -20,17 +20,25 @@ let package = Package(
),
],
dependencies: [
.package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.50.4"),
.package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.52.10"),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "FalClient"),
.target(name: "FalClient"),
.testTarget(
name: "FalClientTests",
dependencies: ["FalClient"]
),
.target(name: "FalSampleApp", dependencies: ["FalClient"]),
.target(
name: "FalSampleApp",
dependencies: ["FalClient"],
path: "Sources/Samples/FalSampleApp"
),
.target(
name: "FalRealtimeSampleApp",
dependencies: ["FalClient"],
path: "Sources/Samples/FalRealtimeSampleApp"
),
]
)
14 changes: 7 additions & 7 deletions Sources/FalClient/Client+Codable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public extension Client {
}

func run<Output: Decodable>(
_ id: String,
_ app: String,
input: (some Encodable) = EmptyInput.empty,
options: RunOptions = DefaultRunOptions
) async throws -> Output {
Expand All @@ -28,25 +28,25 @@ public extension Client {
? try JSONSerialization.jsonObject(with: inputData!) as? [String: Any]
: nil

let data = try await sendRequest(id, input: inputData, queryParams: queryParams, options: options)
let url = buildUrl(fromId: app, path: options.path)
let data = try await sendRequest(url, input: inputData, queryParams: queryParams, options: options)
return try decoder.decode(Output.self, from: data)
}

func subscribe<Output: Decodable>(
_ id: String,
to app: String,
input: (some Encodable) = EmptyInput.empty,
pollInterval: DispatchTimeInterval = .seconds(1),
timeout: DispatchTimeInterval = .minutes(3),
includeLogs: Bool = false,
options _: RunOptions = DefaultRunOptions,
onQueueUpdate: OnQueueUpdate? = nil
) async throws -> Output {
let requestId = try await queue.submit(id, input: input)
let requestId = try await queue.submit(app, input: input)
let start = Int(Date().timeIntervalSince1970 * 1000)
var elapsed = 0
var isCompleted = false
while elapsed < timeout.milliseconds {
let update = try await queue.status(id, of: requestId, includeLogs: includeLogs)
let update = try await queue.status(app, of: requestId, includeLogs: includeLogs)
if let onQueueUpdateCallback = onQueueUpdate {
onQueueUpdateCallback(update)
}
Expand All @@ -60,6 +60,6 @@ public extension Client {
if !isCompleted {
throw FalError.queueTimeout
}
return try await queue.response(id, of: requestId)
return try await queue.response(app, of: requestId)
}
}
5 changes: 2 additions & 3 deletions Sources/FalClient/Client+Request.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import Foundation

extension Client {
func sendRequest(_ id: String, input: Data?, queryParams: [String: Any]? = nil, options: RequestOptions) async throws -> Data {
let urlString = buildUrl(fromId: id, path: options.path)
func sendRequest(_ urlString: String, input: Data?, queryParams: [String: Any]? = nil, options: RunOptions) async throws -> Data {
guard var url = URL(string: urlString) else {
throw FalError.invalidUrl(url: urlString)
}
Expand Down Expand Up @@ -49,6 +48,6 @@ extension Client {

var userAgent: String {
let osVersion = ProcessInfo.processInfo.operatingSystemVersionString
return "fal.ai/swift-client 0.0.1 - \(osVersion)"
return "fal.ai/swift-client 0.1.0 - \(osVersion)"
}
}
27 changes: 13 additions & 14 deletions Sources/FalClient/Client.swift
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import Dispatch
import Foundation

enum HttpMethod: String {
public enum HttpMethod: String {
case get
case post
case put
case delete
}

protocol RequestOptions {
public protocol RequestOptions {
var httpMethod: HttpMethod { get }
var path: String { get }
}

public struct RunOptions: RequestOptions {
let path: String
let httpMethod: HttpMethod
public let path: String
public let httpMethod: HttpMethod

static func withMethod(_ method: HttpMethod) -> Self {
static func withMethod(_ method: HttpMethod) -> RunOptions {
RunOptions(path: "", httpMethod: method)
}

static func route(_ path: String, withMethod method: HttpMethod = .post) -> Self {
static func route(_ path: String, withMethod method: HttpMethod = .post) -> RunOptions {
RunOptions(path: path, httpMethod: method)
}
}
Expand All @@ -35,39 +35,38 @@ public protocol Client {

var queue: Queue { get }

var realtime: Realtime { get }

func run(_ id: String, input: [String: Any]?, options: RunOptions) async throws -> [String: Any]

func subscribe(
_ id: String,
to app: String,
input: [String: Any]?,
pollInterval: DispatchTimeInterval,
timeout: DispatchTimeInterval,
includeLogs: Bool,
options: RunOptions,
onQueueUpdate: OnQueueUpdate?
) async throws -> [String: Any]
}

public extension Client {
func run(_ id: String, input: [String: Any]? = nil, options: RunOptions = DefaultRunOptions) async throws -> [String: Any] {
return try await run(id, input: input, options: options)
func run(_ app: String, input: [String: Any]? = nil, options: RunOptions = DefaultRunOptions) async throws -> [String: Any] {
return try await run(app, input: input, options: options)
}

func subscribe(
_ id: String,
to app: String,
input: [String: Any]? = nil,
pollInterval: DispatchTimeInterval = .seconds(1),
timeout: DispatchTimeInterval = .minutes(3),
includeLogs: Bool = false,
options: RunOptions = DefaultRunOptions,
onQueueUpdate: OnQueueUpdate? = nil
) async throws -> [String: Any] {
return try await subscribe(id,
return try await subscribe(to: app,
input: input,
pollInterval: pollInterval,
timeout: timeout,
includeLogs: includeLogs,
options: options,
onQueueUpdate: onQueueUpdate)
}
}
22 changes: 14 additions & 8 deletions Sources/FalClient/FalClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,31 +29,33 @@ public struct FalClient: Client {

public var queue: Queue { QueueClient(client: self) }

public func run(_ id: String, input: [String: Any]?, options: RunOptions) async throws -> [String: Any] {
public var realtime: Realtime { RealtimeClient(client: self) }

public func run(_ app: String, input: [String: Any]?, options: RunOptions) async throws -> [String: Any] {
let inputData = input != nil ? try JSONSerialization.data(withJSONObject: input as Any) : nil
let queryParams = options.httpMethod == .get ? input : nil
let data = try await sendRequest(id, input: inputData, queryParams: queryParams, options: options)
let url = buildUrl(fromId: app, path: options.path)
let data = try await sendRequest(url, input: inputData, queryParams: queryParams, options: options)
guard let result = try JSONSerialization.jsonObject(with: data) as? [String: Any] else {
throw FalError.invalidResultFormat
}
return result
}

public func subscribe(
_ id: String,
to app: String,
input: [String: Any]?,
pollInterval: DispatchTimeInterval,
timeout: DispatchTimeInterval,
includeLogs: Bool,
options _: RunOptions,
onQueueUpdate: OnQueueUpdate?
) async throws -> [String: Any] {
let requestId = try await queue.submit(id, input: input)
let requestId = try await queue.submit(app, input: input)
let start = Int(Date().timeIntervalSince1970 * 1000)
var elapsed = 0
var isCompleted = false
while elapsed < timeout.milliseconds {
let update = try await queue.status(id, of: requestId, includeLogs: includeLogs)
let update = try await queue.status(app, of: requestId, includeLogs: includeLogs)
if let onQueueUpdateCallback = onQueueUpdate {
onQueueUpdateCallback(update)
}
Expand All @@ -67,12 +69,16 @@ public struct FalClient: Client {
if !isCompleted {
throw FalError.queueTimeout
}
return try await queue.response(id, of: requestId)
return try await queue.response(app, of: requestId)
}
}

public extension FalClient {
static func withProxy(_ url: String) -> FalClient {
static func withProxy(_ url: String) -> Client {
return FalClient(config: ClientConfig(requestProxy: url))
}

static func withCredentials(_ credentials: ClientCredentials) -> Client {
return FalClient(config: ClientConfig(credentials: credentials))
}
}
30 changes: 30 additions & 0 deletions Sources/FalClient/Realtime+Codable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Dispatch
import Foundation

class CodableRealtimeConnection<Input: Encodable>: RealtimeConnection<Input> {
override public func send(_ data: Input) throws {
let json = try JSONEncoder().encode(data)
try sendReference(json)
}
}

public extension Realtime {
func connect<Input: Encodable, Output: Decodable>(
to app: String,
connectionKey: String,
throttleInterval: DispatchTimeInterval,
onResult completion: @escaping (Result<Output, Error>) -> Void
) throws -> RealtimeConnection<Input> {
return handleConnection(
to: app, connectionKey: connectionKey, throttleInterval: throttleInterval,
resultConverter: { data in
let result = try JSONDecoder().decode(Output.self, from: data)
return result
},
connectionFactory: { send, close in
CodableRealtimeConnection(send, close)
},
onResult: completion
)
}
}
Loading

0 comments on commit a46ba25

Please sign in to comment.