Skip to content
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

[ECO-4915] (WIP) Add documentation comments #165

Draft
wants to merge 19 commits into
base: CHA-PR3h-etc
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
7dde7eb
Fix nested symbol links in comments
lawrence-forooghian Nov 28, 2024
c5ef207
Remove links to ably-cocoa in documentation comments
lawrence-forooghian Nov 28, 2024
d1db8c2
Fix mistake in documentation link
lawrence-forooghian Nov 28, 2024
3e09520
Add a basic CI step for checking documentation comments
lawrence-forooghian Nov 28, 2024
14b80a6
TODO remove this commit: add copy of coverage report
lawrence-forooghian Nov 28, 2024
4648742
TODO remove this commit: sort docs coverage table
lawrence-forooghian Nov 28, 2024
c7503b1
Add docstring from JS ChatClient
lawrence-forooghian Nov 28, 2024
61da237
Add docstring from JS ClientOptions
lawrence-forooghian Nov 28, 2024
c3f7406
Add docstring from JS Connection
lawrence-forooghian Nov 28, 2024
51b72dc
Add docstring from JS ConnectionStatus
lawrence-forooghian Nov 28, 2024
4c56496
Add docstring from JS ConnectionStatusChange
lawrence-forooghian Nov 28, 2024
445059b
Add docstring from JS Messages
lawrence-forooghian Nov 28, 2024
ae54b1b
Add docstring from JS SendMessageParams
lawrence-forooghian Nov 28, 2024
b61583c
Add docstring from JS QueryOptions
lawrence-forooghian Nov 28, 2024
428a9b2
Add docstring from JS metadata types
lawrence-forooghian Nov 28, 2024
0085b23
Add docstring from JS headers types
lawrence-forooghian Nov 28, 2024
299b123
Add docstring from JS Reaction
lawrence-forooghian Nov 28, 2024
afb0971
Add docstring from JS Reactions
lawrence-forooghian Nov 28, 2024
5c30183
Add docstring from JS SendReactionParams
lawrence-forooghian Nov 28, 2024
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
16 changes: 16 additions & 0 deletions .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,21 @@ jobs:
- name: Build example app
run: swift run BuildTool build-example-app --platform ${{ matrix.platform }}

check-documentation:
runs-on: macos-15
steps:
- uses: actions/checkout@v4
with:
submodules: true

# This step can be removed once the runners’ default version of Xcode is 16 or above
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: 16

- name: Build documentation
run: swift run BuildTool build-documentation

# We use this job as a marker that all of the required checks have completed.
# This allows us to configure a single required status check in our branch
# protection rules instead of having to type loads of different check names
Expand All @@ -152,6 +167,7 @@ jobs:
- check-spm
- check-xcode
- check-example-app
- check-documentation

steps:
- name: No-op
Expand Down
20 changes: 19 additions & 1 deletion AblyChat.xcworkspace/xcshareddata/swiftpm/Package.resolved
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "1ad2d7338668d15feccbf564582941161acd47349bfca8f34374e11c69677ae8",
"originHash" : "1547951218aae39e26117fe3ca69bba0858841246ead50ef24e9592cdbcfa481",
"pins" : [
{
"identity" : "ably-cocoa",
Expand Down Expand Up @@ -55,6 +55,24 @@
"version" : "1.1.2"
}
},
{
"identity" : "swift-docc-plugin",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-docc-plugin",
"state" : {
"revision" : "85e4bb4e1cd62cec64a4b8e769dcefdf0c5b9d64",
"version" : "1.4.3"
}
},
{
"identity" : "swift-docc-symbolkit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/swiftlang/swift-docc-symbolkit",
"state" : {
"revision" : "b45d1f2ed151d057b54504d653e0da5552844e34",
"version" : "1.0.0"
}
},
{
"identity" : "table",
"kind" : "remoteSourceControl",
Expand Down
20 changes: 19 additions & 1 deletion Package.resolved
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "b6d25f160b01b473629481d68d4fe734b3981fcd87079531f784c2ade3afdc4d",
"originHash" : "19ff3d71167d4ac328655c520d3210baa89ea2c1b0900fb1b5ac5c770b42fa28",
"pins" : [
{
"identity" : "ably-cocoa",
Expand Down Expand Up @@ -55,6 +55,24 @@
"version" : "1.1.2"
}
},
{
"identity" : "swift-docc-plugin",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-docc-plugin",
"state" : {
"revision" : "85e4bb4e1cd62cec64a4b8e769dcefdf0c5b9d64",
"version" : "1.4.3"
}
},
{
"identity" : "swift-docc-symbolkit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/swiftlang/swift-docc-symbolkit",
"state" : {
"revision" : "b45d1f2ed151d057b54504d653e0da5552844e34",
"version" : "1.0.0"
}
},
{
"identity" : "table",
"kind" : "remoteSourceControl",
Expand Down
4 changes: 4 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ let package = Package(
url: "https://github.com/JanGorman/Table.git",
from: "1.1.1"
),
.package(
url: "https://github.com/apple/swift-docc-plugin",
from: "1.0.0"
),
],
targets: [
.target(
Expand Down
54 changes: 54 additions & 0 deletions Sources/AblyChat/ChatClient.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,48 @@
import Ably

public protocol ChatClient: AnyObject, Sendable {
/**
* Returns the rooms object, which provides access to chat rooms.
*
* - Returns: The rooms object.
*/
var rooms: any Rooms { get }

/**
* Returns the underlying connection to Ably, which can be used to monitor the clients
* connection to Ably servers.
*
* - Returns: The connection object.
*/
var connection: any Connection { get }

/**
* Returns the clientId of the current client.
*
* - Returns: The clientId.
*/
var clientID: String { get }

/**
* Returns the underlying Ably Realtime client.
*
* - Returns: The Ably Realtime client.
*/
var realtime: RealtimeClient { get }

/**
* Returns the resolved client options for the client, including any defaults that have been set.
*
* - Returns: The client options.
*/
var clientOptions: ClientOptions { get }
}

public typealias RealtimeClient = any RealtimeClientProtocol

/**
* This is the core client for Ably chat. It provides access to chat rooms.
*/
public actor DefaultChatClient: ChatClient {
public let realtime: RealtimeClient
public nonisolated let clientOptions: ClientOptions
Expand All @@ -20,6 +53,13 @@ public actor DefaultChatClient: ChatClient {
// (CHA-CS4) The chat client must allow its connection status to be observed by clients.
public nonisolated let connection: any Connection

/**
* Constructor for Chat
*
* - Parameters:
* - realtime: The Ably Realtime client.
* - clientOptions: The client options.
*/
public init(realtime: RealtimeClient, clientOptions: ClientOptions?) {
self.realtime = realtime
self.clientOptions = clientOptions ?? .init()
Expand All @@ -34,8 +74,22 @@ public actor DefaultChatClient: ChatClient {
}
}

/**
* Configuration options for the chat client.
*/
public struct ClientOptions: Sendable {
/**
* A custom log handler that will be used to log messages from the client.
*
* By default, the client will log messages to the console.
*/
public var logHandler: LogHandler?

/**
* The minimum log level at which messages will be logged.
*
* By default, LogLevel.error will be used.
*/
public var logLevel: LogLevel?

public init(logHandler: (any LogHandler)? = nil, logLevel: LogLevel? = nil) {
Expand Down
67 changes: 67 additions & 0 deletions Sources/AblyChat/Connection.swift
Original file line number Diff line number Diff line change
@@ -1,24 +1,72 @@
import Ably

/**
* Represents a connection to Ably.
*/
public protocol Connection: AnyObject, Sendable {
/**
* The current status of the connection.
*/
var status: ConnectionStatus { get async }

// TODO: (https://github.com/ably-labs/ably-chat-swift/issues/12): consider how to avoid the need for an unwrap
/**
* The current error, if any, that caused the connection to enter the current status.
*/
var error: ARTErrorInfo? { get async }

/**
* Registers a listener that will be called whenever the connection status changes.
* @param listener The function to call when the status changes.
* @returns An object that can be used to unregister the listener.
*/
func onStatusChange(bufferingPolicy: BufferingPolicy) -> Subscription<ConnectionStatusChange>
}

/**
* The different states that the connection can be in through its lifecycle.
*/
public enum ConnectionStatus: Sendable {
// (CHA-CS1a) The INITIALIZED status is a default status when the realtime client is first initialized. This value will only (likely) be seen if the realtime client doesn’t have autoconnect turned on.

/**
* A temporary state for when the library is first initialized.
*/
case initialized

// (CHA-CS1b) The CONNECTING status is used when the client is in the process of connecting to Ably servers.

/**
* The library is currently connecting to Ably.
*/
case connecting

// (CHA-CS1c) The CONNECTED status is used when the client connected to Ably servers.

/**
* The library is currently connected to Ably.
*/
case connected

// (CHA-CS1d) The DISCONNECTED status is used when the client is not currently connected to Ably servers. This state may be temporary as the underlying Realtime SDK seeks to reconnect.

/**
* The library is currently disconnected from Ably, but will attempt to reconnect.
*/
case disconnected

// (CHA-CS1e) The SUSPENDED status is used when the client is in an extended state of disconnection, but will attempt to reconnect.

/**
* The library is in an extended state of disconnection, but will attempt to reconnect.
*/
case suspended

// (CHA-CS1f) The FAILED status is used when the client is disconnected from the Ably servers due to some non-retriable failure such as authentication failure. It will not attempt to reconnect.

/**
* The library is currently disconnected from Ably and will not attempt to reconnect.
*/
case failed

internal init(from realtimeConnectionState: ARTRealtimeConnectionState) {
Expand All @@ -41,11 +89,30 @@ public enum ConnectionStatus: Sendable {
}
}

/**
* Represents a change in the status of the connection.
*/
public struct ConnectionStatusChange: Sendable {
/**
* The new status of the connection.
*/
public var current: ConnectionStatus

/**
* The previous status of the connection.
*/
public var previous: ConnectionStatus

// TODO: (https://github.com/ably-labs/ably-chat-swift/issues/12): consider how to avoid the need for an unwrap
/**
* An error that provides a reason why the connection has
* entered the new status, if applicable.
*/
public var error: ARTErrorInfo?

/**
* The time in milliseconds that the client will wait before attempting to reconnect.
*/
public var retryIn: TimeInterval

public init(current: ConnectionStatus, previous: ConnectionStatus, error: ARTErrorInfo? = nil, retryIn: TimeInterval) {
Expand Down
4 changes: 2 additions & 2 deletions Sources/AblyChat/Dependencies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ public protocol RealtimeClientProtocol: ARTRealtimeProtocol, Sendable {
var connection: Connection { get }
}

/// Expresses the requirements of the object returned by ``RealtimeClientProtocol.channels``.
/// Expresses the requirements of the object returned by ``RealtimeClientProtocol/channels``.
public protocol RealtimeChannelsProtocol: ARTRealtimeChannelsProtocol, Sendable {
associatedtype Channel: RealtimeChannelProtocol

// It’s not clear to me why ARTRealtimeChannelsProtocol doesn’t include this function (https://github.com/ably/ably-cocoa/issues/1968).
func get(_ name: String, options: ARTRealtimeChannelOptions) -> Channel
}

/// Expresses the requirements of the object returned by ``RealtimeChannelsProtocol.get(_:)``.
/// Expresses the requirements of the object returned by ``RealtimeChannelsProtocol/get(_:options:)``.
public protocol RealtimeChannelProtocol: ARTRealtimeChannelProtocol, Sendable {}

public protocol ConnectionProtocol: ARTConnectionProtocol, Sendable {}
Expand Down
16 changes: 8 additions & 8 deletions Sources/AblyChat/Errors.swift
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import Ably

/**
The error domain used for the ``Ably.ARTErrorInfo`` error instances thrown by the Ably Chat SDK.
The error domain used for the `ARTErrorInfo` error instances thrown by the Ably Chat SDK.

See ``ErrorCode`` for the possible ``ARTErrorInfo.code`` values.
See ``ErrorCode`` for the possible `code` values.
*/
public let errorDomain = "AblyChatErrorDomain"

/**
The error codes for errors in the ``errorDomain`` error domain.
*/
public enum ErrorCode: Int {
/// ``Rooms.get(roomID:options:)`` was called with a different set of room options than was used on a previous call. You must first release the existing room instance using ``Rooms.release(roomID:)``.
/// ``Rooms/get(roomID:options:)`` was called with a different set of room options than was used on a previous call. You must first release the existing room instance using ``Rooms/release(roomID:)``.
///
/// TODO this code is a guess, revisit in https://github.com/ably-labs/ably-chat-swift/issues/32
case inconsistentRoomOptions = 1
Expand Down Expand Up @@ -84,7 +84,7 @@ public enum ErrorCode: Int {
}
}

/// The ``ARTErrorInfo.statusCode`` that should be returned for this error.
/// The ``ARTErrorInfo/statusCode`` that should be returned for this error.
internal var statusCode: Int {
// These status codes are taken from the "Chat-specific Error Codes" section of the spec.
switch self {
Expand Down Expand Up @@ -129,7 +129,7 @@ internal enum ErrorCodeAndStatusCode {
case fixedStatusCode(ErrorCode.CaseThatImpliesFixedStatusCode)
case variableStatusCode(ErrorCode.CaseThatImpliesVariableStatusCode, statusCode: Int)

/// The ``ARTErrorInfo.code`` that should be returned for this error.
/// The ``ARTErrorInfo/code`` that should be returned for this error.
internal var code: ErrorCode {
switch self {
case let .fixedStatusCode(code):
Expand All @@ -139,7 +139,7 @@ internal enum ErrorCodeAndStatusCode {
}
}

/// The ``ARTErrorInfo.statusCode`` that should be returned for this error.
/// The ``ARTErrorInfo/statusCode`` that should be returned for this error.
internal var statusCode: Int {
switch self {
case let .fixedStatusCode(code):
Expand Down Expand Up @@ -245,7 +245,7 @@ internal enum ChatError {
return "The \(descriptionOfFeature(feature)) feature failed to \(operationDescription)."
}

/// The ``ARTErrorInfo.localizedDescription`` that should be returned for this error.
/// The ``ARTErrorInfo/localizedDescription`` that should be returned for this error.
internal var localizedDescription: String {
switch self {
case let .inconsistentRoomOptions(requested, existing):
Expand All @@ -267,7 +267,7 @@ internal enum ChatError {
}
}

/// The ``ARTErrorInfo.cause`` that should be returned for this error.
/// The ``ARTErrorInfo/cause`` that should be returned for this error.
internal var cause: ARTErrorInfo? {
switch self {
case let .attachmentFailed(_, underlyingError):
Expand Down
15 changes: 15 additions & 0 deletions Sources/AblyChat/Headers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,19 @@ public enum HeadersValue: Sendable, Codable, Equatable {
// The corresponding type in TypeScript is
// Record<string, number | string | boolean | null | undefined>
// There may be a better way to represent it in Swift; this will do for now. Have omitted `undefined` because I don’t know how that would occur.

/**
* Headers are a flat key-value map that can be attached to chat messages.
*
* The headers are a flat key-value map and are sent as part of the realtime
* message's extras inside the `headers` property. They can serve similar
* purposes as Metadata but as opposed to Metadata they are read by Ably and
* can be used for features such as
* [subscription filters](https://faqs.ably.com/subscription-filters).
*
* Do not use the headers for authoritative information. There is no
* server-side validation. When reading the headers treat them like user
* input.
*
*/
public typealias Headers = [String: HeadersValue]
Loading
Loading