Skip to content

Commit

Permalink
Added documentation comments (based on JS repo in 69ea478). Adopted t…
Browse files Browse the repository at this point in the history
…o swift docc syntax.
  • Loading branch information
maratal authored and umair-ably committed Dec 12, 2024
1 parent c1915d4 commit 074df6e
Show file tree
Hide file tree
Showing 29 changed files with 1,611 additions and 41 deletions.
45 changes: 45 additions & 0 deletions .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,50 @@ jobs:
- name: Build example app
run: swift run BuildTool build-example-app --platform ${{ matrix.platform }}

check-documentation:
runs-on: macos-15

permissions:
deployments: write
id-token: write
contents: read

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

# Build the documentation using Swift DocC
- name: Build documentation
run: |
PR_NUMBER=${{ github.event.pull_request.number }}
swift package generate-documentation --target AblyChat --disable-indexing \
--hosting-base-path "/builds/ably/ably-chat-swift/pull/${PR_NUMBER}/AblyChat" \
--transform-for-static-hosting
working-directory: ${{ github.workspace }}

# Configure AWS credentials for uploading documentation
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: eu-west-2
role-to-assume: arn:aws:iam::${{ secrets.ABLY_AWS_ACCOUNT_ID_SDK }}:role/ably-sdk-builds-ably-chat-swift
role-session-name: "${{ github.run_id }}-${{ github.run_number }}"

# Upload the generated documentation
- name: Upload Documentation
uses: ably/sdk-upload-action@v2
with:
sourcePath: .build/plugins/Swift-DocC/outputs/AblyChat.doccarchive # Path to the Swift DocC output folder
githubToken: ${{ secrets.GITHUB_TOKEN }}
artifactName: AblyChat # Optional root-level directory name
destinationPath: "builds/ably/ably-chat-swift/pull/${{ github.event.pull_request.number }}/AblyChat" # Destination path on S3

# 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 @@ -193,6 +237,7 @@ jobs:
- build-and-test-xcode
- build-release-configuration-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" : "1d806168af5c6dfac34494fc5941d89fb9d4f96e4803f3a16742053db45c2b49",
"originHash" : "7cf5aad170e2009b8ed30136589be3e449ac79a630487eb65f95143b02db577f",
"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" : "87bdf964454a6a566cd3557b1ae36935d1d19b6a8a8073b9fce67464d6593572",
"originHash" : "f5dd87027f1300f852cf86019686409a47c851bc11433a4138c8956b8a09ad6f",
"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 @@ -34,6 +34,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
6 changes: 4 additions & 2 deletions Sources/AblyChat/BufferingPolicy.swift
Original file line number Diff line number Diff line change
@@ -1,5 +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.)
/**
* 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: Sendable {
case unbounded
case bufferingOldest(Int)
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
73 changes: 72 additions & 1 deletion Sources/AblyChat/Connection.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
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 }

/**
* Subscribes a given listener to a connection status changes.
*
* - Parameters:
* - bufferingPolicy: The ``BufferingPolicy`` for the created subscription.
*
* - Returns: A subscription `AsyncSequence` that can be used to iterate through ``ConnectionStatusChange`` events.
*/
func onStatusChange(bufferingPolicy: BufferingPolicy) -> Subscription<ConnectionStatusChange>
/// Same as calling ``onStatusChange(bufferingPolicy:)`` with ``BufferingPolicy.unbounded``.

/// Same as calling ``onStatusChange(bufferingPolicy:)`` with ``BufferingPolicy/unbounded``.
///
/// The `Connection` protocol provides a default implementation of this method.
func onStatusChange() -> Subscription<ConnectionStatusChange>
Expand All @@ -17,18 +37,50 @@ public extension Connection {
}
}

/**
* 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 @@ -51,11 +103,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
14 changes: 13 additions & 1 deletion Sources/AblyChat/EmitsDiscontinuities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,21 @@ public struct DiscontinuityEvent: Sendable, Equatable {
}
}

/**
* An interface to be implemented by objects that can emit discontinuities to listeners.
*/
public protocol EmitsDiscontinuities {
/**
* Subscribes a given listener to a detected discontinuity.
*
* - Parameters:
* - bufferingPolicy: The ``BufferingPolicy`` for the created subscription.
*
* - Returns: A subscription `AsyncSequence` that can be used to iterate through ``DiscontinuityEvent`` events.
*/
func onDiscontinuity(bufferingPolicy: BufferingPolicy) async -> Subscription<DiscontinuityEvent>
/// Same as calling ``onDiscontinuity(bufferingPolicy:)`` with ``BufferingPolicy.unbounded``.

/// Same as calling ``onDiscontinuity(bufferingPolicy:)`` with ``BufferingPolicy/unbounded``.
///
/// The `EmitsDiscontinuities` protocol provides a default implementation of this method.
func onDiscontinuity() async -> Subscription<DiscontinuityEvent>
Expand Down
Loading

0 comments on commit 074df6e

Please sign in to comment.