Skip to content
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
35 changes: 35 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,38 @@ jobs:
uses: codecov/codecov-action@v5
with:
slug: otaviocc/MicroClient

test-linux:
name: Test on Linux (Swift ${{ matrix.swift-version }})
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
swift-version: ["6.0", "6.2"]

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Swift
uses: swift-actions/setup-swift@v2
with:
swift-version: ${{ matrix.swift-version }}

- name: Cache Swift Package Manager
uses: actions/cache@v4
with:
path: |
.build
~/.cache/org.swift.swiftpm
key: ${{ runner.os }}-spm-${{ matrix.swift-version }}-v1
restore-keys: |
${{ runner.os }}-spm-${{ matrix.swift-version }}-
${{ runner.os }}-spm-

- name: Build
run: swift build

- name: Run tests
run: swift test
3 changes: 2 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ jobs:

- **macOS**: 12.0+
- **iOS**: 15.0+
- **Linux**: Swift 6.0+ toolchain
- **Swift**: 6.0+

### 📚 Installation
Expand Down Expand Up @@ -139,7 +140,7 @@ jobs:
- ✅ **Modern Swift**: Built with async/await and Swift concurrency
- ✅ **Zero dependencies**: Pure Swift implementation
- ✅ **Flexible**: Configurable encoders, decoders, and interceptors
- ✅ **Combine support**: Publisher for client status monitoring
- ✅ **Cross-platform**: macOS, iOS, and Linux
- ✅ **Comprehensive testing**: Extensive test coverage with Swift Testing

EOF
Expand Down
3 changes: 1 addition & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Overview

MicroClient is a lightweight, zero-dependency Swift networking library designed for type-safe HTTP requests using modern Swift concurrency. The package targets macOS 12+ and iOS 15+, using Swift tools version 6.0.
MicroClient is a lightweight, zero-dependency Swift networking library designed for type-safe HTTP requests using modern Swift concurrency. The package targets macOS 12+, iOS 15+, and Linux, using Swift tools version 6.0.

## Development Commands

Expand Down Expand Up @@ -37,7 +37,6 @@ The library is built around four main types that work together:

1. **NetworkClient** - The main client interface (`NetworkClientProtocol` + `NetworkClient`)
- Async/await API for making requests
- Combine integration with status publisher
- Request interceptor support for middleware

2. **NetworkRequest<RequestModel, ResponseModel>** - Type-safe request definitions
Expand Down
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ A lightweight, zero-dependency Swift networking library designed for type-safe H
- 🔁 **Automatic Retries**: Built-in support for request retries
- 🪵 **Advanced Logging**: Customizable logging for requests and responses
- ❌ **Task Cancellation**: Full support for Swift structured concurrency cancellation
- 📱 **Cross-platform**: Supports macOS 12+ and iOS 15+
- 📱 **Cross-platform**: Supports macOS 12+, iOS 15+, and Linux

## Requirements

- Swift 6.0+
- macOS 12.0+ / iOS 15.0+
- Linux (Swift 6.0+ toolchain)

## Installation

Expand All @@ -35,6 +36,19 @@ dependencies: [
]
```

### Linux

MicroClient builds and runs on Linux. Because Foundation's URL loading system (`URLRequest`,
`URLResponse`, `URLSession`) lives in the separate `FoundationNetworking` module there, add the
standard conditional import wherever you name those types:

```swift
import MicroClient
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
```

## Quick Start

### 1. Create a Configuration
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/Extensions/URLRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

extension URLRequest {

Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/Extensions/URLResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

public extension URLResponse {

Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/Extensions/URLSessionProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// Protocol for URLSession to enable dependency injection and testing
public protocol URLSessionProtocol: Sendable {
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/Interceptors/APIKeyInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// An interceptor that adds API key authentication to HTTP requests.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// An interceptor that adds Accept headers to HTTP requests.
///
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/Interceptors/BasicAuthInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// An interceptor that adds Basic authentication to HTTP requests.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// An interceptor that adds Bearer token authorization to HTTP requests.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// An interceptor that adds Cache-Control headers to HTTP requests.
///
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/Interceptors/ContentTypeInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// An interceptor that adds Content-Type headers to HTTP requests with a body.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// A protocol for receiving metrics collected from network responses.
public protocol MetricsCollector: Sendable {
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/Interceptors/RequestIDInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// An interceptor that adds unique request IDs to HTTP requests.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// An interceptor that logs response information including status code, headers, and body data.
///
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/Interceptors/RetryAfterInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// Error thrown when a Retry-After header indicates the client should wait before retrying.
public struct RetryAfterError: Error {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// An interceptor that validates HTTP status codes against a custom range or set of acceptable codes.
///
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/Interceptors/TimeoutInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// An interceptor that configures custom timeout intervals for HTTP requests.
///
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/Interceptors/UserAgentInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// An interceptor that adds a User-Agent header to HTTP requests.
///
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/NetworkClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// The network client interface.
public protocol NetworkClientProtocol: Sendable {
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/NetworkClientError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// An enum representing possible errors that can occur during a network request.
public enum NetworkClientError: Error {
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/NetworkConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// The network client configuration.
public struct NetworkConfiguration: Sendable {
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/NetworkRequestInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// A protocol for intercepting and modifying network requests before they are sent.
public protocol NetworkRequestInterceptor: Sendable {
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/NetworkResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// The network response. It has the type
/// used as response model.
Expand Down
3 changes: 3 additions & 0 deletions Sources/MicroClient/NetworkResponseInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

/// A protocol for intercepting and processing network responses after they are received and decoded.
public protocol NetworkResponseInterceptor: Sendable {
Expand Down
3 changes: 3 additions & 0 deletions Tests/MicroClientTests/APIKeyInterceptorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
import Testing
@testable import MicroClient

Expand Down
3 changes: 3 additions & 0 deletions Tests/MicroClientTests/AcceptHeaderInterceptorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
import Testing
@testable import MicroClient

Expand Down
3 changes: 3 additions & 0 deletions Tests/MicroClientTests/BasicAuthInterceptorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
import Testing
@testable import MicroClient

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
import Testing
@testable import MicroClient

Expand Down
3 changes: 3 additions & 0 deletions Tests/MicroClientTests/CacheControlInterceptorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
import Testing
@testable import MicroClient

Expand Down
3 changes: 3 additions & 0 deletions Tests/MicroClientTests/ContentTypeInterceptorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
import Testing
@testable import MicroClient

Expand Down
3 changes: 3 additions & 0 deletions Tests/MicroClientTests/Doubles/HeaderInterceptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// SOFTWARE.

import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
@testable import MicroClient

struct HeaderInterceptor: NetworkRequestInterceptor {
Expand Down
Loading
Loading