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

docs: add missing documentation for public types #64

Merged
merged 2 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ format-swift-format:
swift format --configuration .swift-format --in-place --recursive Sources Tests Dangerfile.swift Package.swift

format-swiftlint:
swiftlint --fix --config .swiftlint.yml Sources Tests
swiftlint --fix --config .swiftlint.yml --quiet Sources Tests Dangerfile.swift Package.swift

build:
swift build
Expand All @@ -23,4 +23,4 @@ lint-swift-format:
swift format lint --configuration .swift-format --strict --recursive Sources Tests Dangerfile.swift Package.swift

lint-swiftlint:
swiftlint lint --config .swiftlint.yml Sources Tests
swiftlint lint --config .swiftlint.yml --strict --quiet Sources Tests Dangerfile.swift Package.swift
51 changes: 51 additions & 0 deletions Sources/Postie/APIError.swift
Original file line number Diff line number Diff line change
@@ -1,21 +1,69 @@
import Foundation

/// Represents various errors that can occur when interacting with the API.
///
/// The `APIError` enum provides a comprehensive list of errors that can occur when interacting with the API.
/// Each case represents a specific type of error, and the associated values provide additional context or information
/// about the error.
///
/// - SeeAlso: `LocalizedError` for more information on localized error descriptions.
public enum APIError: LocalizedError {
/// Indicates a response error with a specific status code and data.
///
/// This error occurs when the API returns a response with a non-success status code.
/// The associated values provide the status code and the response data.
///
/// - Parameters:
/// - statusCode: The HTTP status code of the response.
/// - data: The response data.
case responseError(statusCode: Int, data: Data)

/// Indicates an invalid response.
///
/// This error occurs when the API returns an invalid response, such as a response with missing or malformed data.
case invalidResponse

/// Indicates a URL error.
///
/// This error occurs when there is an issue with the URL, such as a network connectivity problem or an invalid URL.
///
/// - Parameter error: The underlying `URLError` that caused the failure.
case urlError(URLError)

/// Indicates a decoding error.
///
/// This error occurs when there is an issue decoding the response data into the expected type.
///
/// - Parameter error: The underlying `DecodingError` that caused the failure.
case decodingError(DecodingError)

/// Indicates a failure to encode plain text with a specific encoding.
///
/// This error occurs when there is an issue encoding plain text data using the specified encoding.
///
/// - Parameter encoding: The `String.Encoding` used for encoding.
case failedToEncodePlainText(encoding: String.Encoding)

/// Indicates an unknown error.
///
/// This error occurs when an unknown error is encountered.
///
/// - Parameter error: The underlying `Error` that caused the failure.
case unknown(error: Error)

/// A localized message describing what error occurred.
///
/// This property provides a human-readable description of the error, which can be used for displaying error messages
/// to the user.
///
/// - Returns: A localized string describing the error.
///
/// Example usage:
/// ```
/// let error: APIError = .invalidResponse
/// print(error.errorDescription ?? "Unknown error")
/// // Output: "Received invalid URL response"
/// ```
public var errorDescription: String? {
switch self {
case let .responseError(statusCode, data):
Expand Down Expand Up @@ -46,6 +94,9 @@ public enum APIError: LocalizedError {

/// Converts a coding path to a string representation.
///
/// This method takes a coding path, which is an array of `CodingKey` objects, and converts it to a string representation.
/// The resulting string is a dot-separated list of the keys in the coding path.
///
/// - Parameter codingPath: The coding path to convert.
/// - Returns: A string representation of the coding path.
private func codingPathToString(_ codingPath: [CodingKey]) -> String {
Expand Down
13 changes: 13 additions & 0 deletions Sources/Postie/Cookies/RequestCookies.swift
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
import Foundation

/// A property wrapper that provides a convenient way to handle HTTP cookies in a request.
///
/// Example usage:
/// ```
/// @RequestCookies var cookies: [HTTPCookie]
/// ```
/// This property wrapper can be used to manage HTTP cookies in a request.
@propertyWrapper
public struct RequestCookies {
/// The wrapped value representing an array of `HTTPCookie` objects.
///
/// This property holds the array of `HTTPCookie` objects that are managed by this property wrapper.
public var wrappedValue: [HTTPCookie]

/// Initializes a new instance of `RequestCookies` with an optional array of `HTTPCookie` objects.
///
/// - Parameter wrappedValue: An array of `HTTPCookie` objects. Defaults to an empty array.
///
/// Example usage:
/// ```
/// @RequestCookies var cookies: [HTTPCookie] = [cookie1, cookie2]
/// ```
public init(wrappedValue: [HTTPCookie] = []) {
self.wrappedValue = wrappedValue
}
Expand Down
13 changes: 13 additions & 0 deletions Sources/Postie/Cookies/ResponseCookies.swift
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
import Foundation

/// A property wrapper that provides a convenient way to handle HTTP cookies in a response.
///
/// Example usage:
/// ```
/// @ResponseCookies var cookies: [HTTPCookie]
/// ```
/// This property wrapper can be used to manage HTTP cookies in a response.
@propertyWrapper
public struct ResponseCookies {
/// The wrapped value representing an array of `HTTPCookie` objects.
///
/// This property holds the array of `HTTPCookie` objects that are managed by this property wrapper.
public var wrappedValue: [HTTPCookie]

/// Initializes a new instance of `ResponseCookies` with an optional array of `HTTPCookie` objects.
///
/// - Parameter wrappedValue: An array of `HTTPCookie` objects. Defaults to an empty array.
///
/// Example usage:
/// ```
/// @ResponseCookies var cookies: [HTTPCookie] = [cookie1, cookie2]
/// ```
public init(wrappedValue: [HTTPCookie] = []) {
self.wrappedValue = wrappedValue
}
Expand Down
3 changes: 2 additions & 1 deletion Sources/Postie/HTTPAPIClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Combine
import Foundation
import os.log

// swiftlint:disable:next type_body_length
// swiftlint:disable file_length type_body_length
/// A class responsible for sending HTTP API requests and handling responses.
///
/// The `HTTPAPIClient` class provides methods to send HTTP API requests using different encoding formats
Expand Down Expand Up @@ -592,3 +592,4 @@ open class HTTPAPIClient {
return url.appendingPathComponent(prefix)
}
}
// swiftlint:enable file_length type_body_length
30 changes: 30 additions & 0 deletions Sources/Postie/Headers/RequestHeader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,31 @@ internal protocol RequestHeaderProtocol {
}

/// A property wrapper that provides a convenient way to handle HTTP headers in a request.
///
/// Example usage:
/// ```
/// @RequestHeader var header: String
/// ```
/// This property wrapper can be used to manage HTTP headers in a request.
@propertyWrapper
public struct RequestHeader<T> where T: RequestHeaderValue {
/// The custom name of the header item, can be nil.
///
/// This property holds the custom name of the header item, which can be nil.
public var name: String?
/// The wrapped value representing the header value.
///
/// This property holds the wrapped value representing the header value.
public var wrappedValue: T

/// Initializes a new instance of `RequestHeader` with the specified wrapped value.
///
/// - Parameter wrappedValue: The wrapped value representing the header value.
///
/// Example usage:
/// ```
/// @RequestHeader var header: String = "value"
/// ```
public init(wrappedValue: T) {
self.wrappedValue = wrappedValue
}
Expand All @@ -26,6 +41,11 @@ public struct RequestHeader<T> where T: RequestHeaderValue {
/// - Parameters:
/// - name: The custom name of the header item, can be nil.
/// - defaultValue: The default value representing the header value.
///
/// Example usage:
/// ```
/// @RequestHeader(name: "Custom-Header") var header: String = "value"
/// ```
public init(name: String? = nil, defaultValue: T) {
self.name = name
wrappedValue = defaultValue
Expand All @@ -36,6 +56,11 @@ extension RequestHeader where T == String {
/// Initializes a new instance of `RequestHeader` with the specified name and an empty string as the default value.
///
/// - Parameter name: The custom name of the header item, can be nil.
///
/// Example usage:
/// ```
/// @RequestHeader(name: "Custom-Header") var header: String
/// ```
public init(name: String?) {
self.name = name
wrappedValue = ""
Expand All @@ -46,6 +71,11 @@ extension RequestHeader where T == String? {
/// Initializes a new instance of `RequestHeader` with the specified name and a nil value as the default value.
///
/// - Parameter name: The custom name of the header item, can be nil.
///
/// Example usage:
/// ```
/// @RequestHeader(name: "Custom-Header") var header: String?
/// ```
public init(name: String?) {
self.name = name
wrappedValue = nil
Expand Down
3 changes: 3 additions & 0 deletions Sources/Postie/Headers/RequestHeaderValue.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
public protocol RequestHeaderValue {
/// The serialized value of the header.
///
/// This property represents the serialized value of the header.
/// It is used to convert the header value into a string format suitable for HTTP headers.
var serializedHeaderValue: String? { get }
}

Expand Down
57 changes: 57 additions & 0 deletions Sources/Postie/Networking/URLSessionProvider.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,68 @@
import Combine
import Foundation

/// A protocol that provides methods for sending URL requests using different mechanisms.
///
/// The `URLSessionProvider` protocol defines methods for sending URL requests using Combine, callbacks, and async-await.
/// It allows for flexibility in handling URL requests and responses.
public protocol URLSessionProvider {
/// Sends a URL request using Combine and returns a publisher that emits the response.
///
/// - Parameter request: The URL request to send.
/// - Returns: A publisher that emits the response data and URL response, or an error.
///
/// Example usage:
/// ```
/// let provider: URLSessionProvider = URLSession.shared
/// let publisher = provider.send(urlRequest: myRequest)
/// publisher.sink(receiveCompletion: { completion in
/// switch completion {
/// case .finished:
/// print("Request completed successfully")
/// case .failure(let error):
/// print("Request failed with error: \(error)")
/// }
/// }, receiveValue: { output in
/// print("Received response: \(output.response)")
/// print("Received data: \(output.data)")
/// })
/// .store(in: &cancellables)
/// ```
func send(urlRequest request: URLRequest) -> AnyPublisher<URLSession.DataTaskPublisher.Output, URLSession.DataTaskPublisher.Failure>

/// Sends a URL request using a callback to handle the response.
///
/// - Parameters:
/// - request: The URL request to send.
/// - completion: The callback to handle the response.
///
/// Example usage:
/// ```
/// let provider: URLSessionProvider = URLSession.shared
/// provider.send(urlRequest: myRequest) { data, response, error in
/// if let error = error {
/// print("Request failed with error: \(error)")
/// } else if let response = response, let data = data {
/// print("Received response: \(response)")
/// print("Received data: \(data)")
/// }
/// }
/// ```
func send(urlRequest request: URLRequest, completion: @escaping (Data?, URLResponse?, Error?) -> Void)

/// Sends a URL request using async-await and returns the response.
///
/// - Parameter request: The URL request to send.
/// - Returns: A tuple containing the response data and URL response.
/// - Throws: An error if the request fails.
///
/// Example usage:
/// ```
/// let provider: URLSessionProvider = URLSession.shared
/// let (data, response) = try await provider.send(urlRequest: myRequest)
/// print("Received response: \(response)")
/// print("Received data: \(data)")
/// ```
func send(urlRequest request: URLRequest) async throws -> (Data, URLResponse)
}

Expand Down
Loading