-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Based on JS at 0b4b0f8. The entry point is the DefaultChatClient class. Chose to use existential types when one protocol returns another (i.e. `-> any MyProtocol`) instead of associated types, because it’s more readable and I don’t think that we need to worry about the performance implications. turned on explicit_acl, but just for the library — it's a handy thing to have to make sure you've not missed making anything public, but we don’t need it for BuildTool (For future reference, generate memberwise initializers in Xcode by clicking at the start of the type declaration and doing Editor -> Refactor -> Generate Memberwise Initializer.) Skipped copying the docstrings from JS; created #1 to do this later. Turned off missing_docs for now. We’ll be able to validate this API when we do #4, which will create a mock implementation of this API and then build the example app around the mock. Some stuff is up in the air until we start trying to implement, too. maybe have been too liberal with Sendable not sure if the types where `subscribe()` just returns a subscription could be sequences themselves, i still don't understand the nuance of buffering and whatnot, what happens if you share them so the api decided on is that there are no responses, you can directly iterate over what comes out (because there’s no need for an `off()`)
- Loading branch information
1 parent
8c7b0a4
commit 61ae43f
Showing
27 changed files
with
562 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import Ably | ||
|
||
/// A mock implementation of `ARTRealtimeProtocol`. It only exists so that we can construct an instance of `DefaultChatClient` without needing to create a proper `ARTRealtime` instance (which we can’t yet do because we don’t have a method for inserting an API key into the example app). TODO remove this once we start building the example app | ||
class MockRealtime: NSObject, ARTRealtimeProtocol { | ||
var device: ARTLocalDevice { | ||
fatalError("Not implemented") | ||
} | ||
|
||
var clientId: String? | ||
|
||
required init(options _: ARTClientOptions) {} | ||
|
||
required init(key _: String) {} | ||
|
||
required init(token _: String) {} | ||
|
||
func time(_: @escaping ARTDateTimeCallback) { | ||
fatalError("Not implemented") | ||
} | ||
|
||
func ping(_: @escaping ARTCallback) { | ||
fatalError("Not implemented") | ||
} | ||
|
||
func stats(_: @escaping ARTPaginatedStatsCallback) -> Bool { | ||
fatalError("Not implemented") | ||
} | ||
|
||
func stats(_: ARTStatsQuery?, callback _: @escaping ARTPaginatedStatsCallback) throws { | ||
fatalError("Not implemented") | ||
} | ||
|
||
func connect() { | ||
fatalError("Not implemented") | ||
} | ||
|
||
func close() { | ||
fatalError("Not implemented") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
opt_in_rules: | ||
# Opt-in rules of type "idiomatic" that we’ve decided we want: | ||
- explicit_acl |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/// Describes what to do with realtime events that come in faster than the consumer of an `AsyncSequence` can handle them. | ||
/// (This is the same as `AsyncStream<T>.Continuation.BufferingPolicy` but with the generic type parameter `T` removed.) | ||
public enum BufferingPolicy { | ||
case unbounded | ||
case bufferingOldest(Int) | ||
case bufferingNewest(Int) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import Ably | ||
|
||
public protocol ChatClient: AnyObject, Sendable { | ||
var rooms: any Rooms { get } | ||
var connection: any Connection { get } | ||
var clientID: String { get } | ||
var realtime: any ARTRealtimeProtocol { get } | ||
var clientOptions: ClientOptions { get } | ||
} | ||
|
||
public final class DefaultChatClient: ChatClient { | ||
public init(realtime _: ARTRealtimeProtocol, clientOptions _: ClientOptions?) { | ||
// This one doesn’t do `fatalError`, so that I can call it in the example app | ||
} | ||
|
||
public var rooms: any Rooms { | ||
fatalError("Not yet implemented") | ||
} | ||
|
||
public var connection: any Connection { | ||
fatalError("Not yet implemented") | ||
} | ||
|
||
public var clientID: String { | ||
fatalError("Not yet implemented") | ||
} | ||
|
||
public var realtime: any ARTRealtimeProtocol { | ||
fatalError("Not yet implemented") | ||
} | ||
|
||
public var clientOptions: ClientOptions { | ||
fatalError("Not yet implemented") | ||
} | ||
} | ||
|
||
public struct ClientOptions: Sendable { | ||
public var logHandler: LogHandler? | ||
public var logLevel: LogLevel? | ||
|
||
public init(logHandler: (any LogHandler)? = nil, logLevel: LogLevel? = nil) { | ||
self.logHandler = logHandler | ||
self.logLevel = logLevel | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import Ably | ||
|
||
public protocol Connection: AnyObject, Sendable { | ||
var status: any ConnectionStatus { get } | ||
} | ||
|
||
public protocol ConnectionStatus: AnyObject, Sendable { | ||
var current: ConnectionLifecycle { get } | ||
var error: ARTErrorInfo? { get } | ||
func subscribe(bufferingPolicy: BufferingPolicy) -> Subscription<ConnectionStatusChange> | ||
} | ||
|
||
public enum ConnectionLifecycle: Sendable { | ||
case initialized | ||
case connecting | ||
case connected | ||
case disconnected | ||
case suspended | ||
case failed | ||
} | ||
|
||
public struct ConnectionStatusChange: Sendable { | ||
public var current: ConnectionLifecycle | ||
public var previous: ConnectionLifecycle | ||
public var error: ARTErrorInfo? | ||
public var retryIn: TimeInterval | ||
|
||
public init(current: ConnectionLifecycle, previous: ConnectionLifecycle, error: ARTErrorInfo? = nil, retryIn: TimeInterval) { | ||
self.current = current | ||
self.previous = previous | ||
self.error = error | ||
self.retryIn = retryIn | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import Ably | ||
|
||
public protocol EmitsDiscontinuities { | ||
func subscribeToDiscontinuities() -> Subscription<ARTErrorInfo> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
public typealias Headers = Any & Sendable /* TODO: Record<string, number | string | boolean | null | undefined>; */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
public typealias LogContext = [String: Any] | ||
|
||
public protocol LogHandler: AnyObject, Sendable { | ||
func log(message: String, level: LogLevel, context: LogContext?) | ||
} | ||
|
||
public enum LogLevel: Sendable { | ||
case trace | ||
case debug | ||
case info | ||
case warn | ||
case error | ||
case silent | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import Foundation | ||
|
||
public typealias MessageHeaders = Headers | ||
public typealias MessageMetadata = Metadata | ||
|
||
public struct Message: Sendable { | ||
public var timeserial: String | ||
public var clientID: String | ||
public var roomID: String | ||
public var text: String | ||
public var createdAt: Date | ||
public var metadata: MessageMetadata | ||
public var headers: MessageHeaders | ||
|
||
public init(timeserial: String, clientID: String, roomID: String, text: String, createdAt: Date, metadata: any MessageMetadata, headers: any MessageHeaders) { | ||
self.timeserial = timeserial | ||
self.clientID = clientID | ||
self.roomID = roomID | ||
self.text = text | ||
self.createdAt = createdAt | ||
self.metadata = metadata | ||
self.headers = headers | ||
} | ||
|
||
public func isBefore(_: Message) -> Bool { | ||
fatalError("Not yet implemented") | ||
} | ||
|
||
public func isAfter(_: Message) -> Bool { | ||
fatalError("Not yet implemented") | ||
} | ||
|
||
public func isEqual(_: Message) -> Bool { | ||
fatalError("Not yet implemented") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import Ably | ||
|
||
public protocol Messages: AnyObject, Sendable, EmitsDiscontinuities { | ||
func subscribe(bufferingPolicy: BufferingPolicy) -> MessageSubscription | ||
func get(options: QueryOptions) async throws -> any PaginatedResult<Message> | ||
func send(params: SendMessageParams) async throws -> Message | ||
var channel: ARTRealtimeChannelProtocol { get } | ||
} | ||
|
||
public struct SendMessageParams: Sendable { | ||
public var text: String | ||
public var metadata: MessageMetadata? | ||
public var headers: MessageHeaders? | ||
|
||
public init(text: String, metadata: (any MessageMetadata)? = nil, headers: (any MessageHeaders)? = nil) { | ||
self.text = text | ||
self.metadata = metadata | ||
self.headers = headers | ||
} | ||
} | ||
|
||
public struct QueryOptions: Sendable { | ||
public enum Direction: Sendable { | ||
case forwards | ||
case backwards | ||
} | ||
|
||
public var start: Date? | ||
public var end: Date? | ||
public var limit: Int? | ||
public var direction: Direction? | ||
|
||
public init(start: Date? = nil, end: Date? = nil, limit: Int? = nil, direction: QueryOptions.Direction? = nil) { | ||
self.start = start | ||
self.end = end | ||
self.limit = limit | ||
self.direction = direction | ||
} | ||
} | ||
|
||
public struct QueryOptionsWithoutDirection: Sendable { | ||
public var start: Date? | ||
public var end: Date? | ||
public var limit: Int? | ||
|
||
public init(start: Date? = nil, end: Date? = nil, limit: Int? = nil) { | ||
self.start = start | ||
self.end = end | ||
self.limit = limit | ||
} | ||
} | ||
|
||
// TODO: note this will start accumulating messages as soon as created | ||
// TODO: note that I wanted this to instead inherit from Sequence protocol but that's not possible | ||
public struct MessageSubscription: Sendable, AsyncSequence { | ||
public typealias Element = Message | ||
|
||
// TODO: explain, this is a workaround to allow us to write mocks | ||
public init<T: AsyncSequence>(mockAsyncSequence _: T) where T.Element == Element { | ||
fatalError("Not yet implemented") | ||
} | ||
|
||
public func getPreviousMessages(params _: QueryOptionsWithoutDirection) async throws -> any PaginatedResult<Message> { | ||
fatalError("Not yet implemented") | ||
} | ||
|
||
public struct AsyncIterator: AsyncIteratorProtocol { | ||
// note that I’ve removed the `throws` here and that means we don't need a `try` in the loop | ||
public mutating func next() async -> Element? { | ||
fatalError("Not implemented") | ||
} | ||
} | ||
|
||
public func makeAsyncIterator() -> AsyncIterator { | ||
fatalError("Not implemented") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
public typealias Metadata = Any & Sendable // TODO: Record<string, unknown>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
public protocol PaginatedResult<T>: AnyObject, Sendable { | ||
associatedtype T | ||
|
||
var items: [T] { get } | ||
var hasNext: Bool { get } | ||
var isLast: Bool { get } | ||
// TODO: is there a way to link `hasNext` and `next`’s nullability? | ||
var next: (any PaginatedResult<T>)? { get async throws } | ||
var first: any PaginatedResult<T> { get async throws } | ||
var current: Bool { get async throws } | ||
} |
Oops, something went wrong.