{"id":27206476,"url":"https://github.com/siamakrostami/srnetworkmanager","last_synced_at":"2025-12-11T23:01:40.318Z","repository":{"id":252564383,"uuid":"840804529","full_name":"siamakrostami/SRNetworkManager","owner":"siamakrostami","description":"SRNetworkManager is a powerful and flexible networking layer for Swift applications. It provides a generic, protocol-oriented approach to handling API requests, supporting both Combine and async/await paradigms. This package is designed to be easy to use, highly customizable, and fully compatible with Swift 6 and the Sendable protocol.","archived":false,"fork":false,"pushed_at":"2025-04-05T08:12:14.000Z","size":153,"stargazers_count":41,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-11T21:19:43.540Z","etag":null,"topics":["asyncawait","combine-framework","network","swift","threadsafe"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/siamakrostami.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-10T18:25:08.000Z","updated_at":"2025-06-05T12:42:35.000Z","dependencies_parsed_at":"2024-08-10T19:55:42.913Z","dependency_job_id":"532046a5-efde-47b9-8cb2-bf35a5523d12","html_url":"https://github.com/siamakrostami/SRNetworkManager","commit_stats":null,"previous_names":["siamakrostami/srgenericnetworklayer","siamakrostami/srnetworkmanager"],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/siamakrostami/SRNetworkManager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siamakrostami%2FSRNetworkManager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siamakrostami%2FSRNetworkManager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siamakrostami%2FSRNetworkManager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siamakrostami%2FSRNetworkManager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/siamakrostami","download_url":"https://codeload.github.com/siamakrostami/SRNetworkManager/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siamakrostami%2FSRNetworkManager/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261159783,"owners_count":23118084,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asyncawait","combine-framework","network","swift","threadsafe"],"created_at":"2025-04-09T23:41:29.813Z","updated_at":"2025-12-11T23:01:40.311Z","avatar_url":"https://github.com/siamakrostami.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"## What's New\n\n- Updated default URLSession configuration and cache policy\n- Default request cache policy is now `.useProtocolCachePolicy`\n- Support for per-request cache policy overrides via `NetworkRouter`\n- Logging now includes the effective cache policy and configuration snapshot\n- Thread-safe propagation of configuration updates across client instances\n- Tests updated to cover configuration and cache policy behavior\n\n# SRNetworkManager\n\nA comprehensive, thread-safe networking library for Swift applications with support for both Combine and async/await programming models.\n\n## Features\n\n- **🔄 Dual Programming Models**: Support for both Combine and async/await\n- **🛡️ Thread Safety**: All operations are thread-safe with proper synchronization\n- **🔄 Retry Logic**: Configurable retry strategies for failed requests\n- **📤 Upload Support**: File upload with progress tracking\n- **🌊 Streaming**: Support for streaming responses\n- **📡 Network Monitoring**: Real-time network connectivity and VPN detection\n- **🔧 Error Handling**: Rich error types with proper mapping\n- **📝 Logging**: Comprehensive request/response logging with multiple levels\n- **🔐 Authentication**: Built-in support for various authentication methods\n- **📦 Parameter Encoding**: Support for JSON, URL-encoded, and multipart form data\n\n## Requirements\n\n- iOS 13.0+\n- macOS 13.0+\n- tvOS 13.0+\n- watchOS 7.0+\n- Swift 5.9+\n\n## Installation\n\n### Swift Package Manager\n\nAdd the following dependency to your `Package.swift`:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/yourusername/SRNetworkManager.git\", from: \"1.0.0\")\n]\n```\n\nOr add it directly in Xcode:\n1. File → Add Package Dependencies\n2. Enter the repository URL\n3. Select the version you want to use\n\n## Quick Start\n\n### Basic Setup\n\n```swift\nimport SRNetworkManager\n\n// Create a client with default configuration\nlet client = APIClient()\n\n// Define your endpoint\nstruct GetUsersEndpoint: NetworkRouter {\n    var baseURLString: String { \"https://api.example.com\" }\n    var path: String { \"/users\" }\n    var method: RequestMethod? { .get }\n}\n\n// Make a request\nclient.request(GetUsersEndpoint())\n    .sink(\n        receiveCompletion: { completion in\n            if case .failure(let error) = completion {\n                print(\"Error: \\(error)\")\n            }\n        },\n        receiveValue: { (users: [User]) in\n            print(\"Received \\(users.count) users\")\n        }\n    )\n    .store(in: \u0026cancellables)\n```\n\n### Async/Await Usage\n\n```swift\n// Using async/await\ndo {\n    let users: [User] = try await client.request(GetUsersEndpoint())\n    print(\"Received \\(users.count) users\")\n} catch {\n    print(\"Error: \\(error)\")\n}\n```\n\n## Core Components\n\n### APIClient\n\nThe main client for making network requests.\n\n```swift\nlet client = APIClient(\n    configuration: .default,\n    qos: .userInitiated,\n    logLevel: .standard,\n    decoder: JSONDecoder(),\n    retryHandler: DefaultRetryHandler(numberOfRetries: 3)\n)\n```\n\n### NetworkRouter\n\nDefine your API endpoints with type safety.\n\n```swift\nstruct CreateUserEndpoint: NetworkRouter {\n    struct Parameters: Codable {\n        let name: String\n        let email: String\n    }\n    \n    var baseURLString: String { \"https://api.example.com\" }\n    var path: String { \"/users\" }\n    var method: RequestMethod? { .post }\n    var params: Parameters? { parameters }\n    \n    private let parameters: Parameters\n    init(name: String, email: String) {\n        self.parameters = Parameters(name: name, email: email)\n    }\n}\n```\n\n### Network Monitoring\n\nMonitor network connectivity changes in real-time.\n\n```swift\nlet monitor = NetworkMonitor()\nmonitor.startMonitoring()\n\nmonitor.status\n    .sink { connectivity in\n        switch connectivity {\n        case .disconnected:\n            print(\"Network disconnected\")\n        case .connected(let networkType):\n            print(\"Connected via \\(networkType)\")\n        }\n    }\n    .store(in: \u0026cancellables)\n```\n\n## Advanced Usage\n\n### File Upload with Progress\n\n```swift\nlet endpoint = UploadEndpoint()\nlet imageData = UIImage().jpegData(compressionQuality: 0.8)\n\nclient.uploadRequest(endpoint, withName: \"image\", data: imageData) { progress in\n    print(\"Upload progress: \\(Int(progress * 100))%\")\n}\n.sink(\n    receiveCompletion: { completion in\n        print(\"Upload completed\")\n    },\n    receiveValue: { (response: UploadResponse) in\n        print(\"Upload successful: \\(response.url)\")\n    }\n)\n.store(in: \u0026cancellables)\n```\n\n### Streaming Responses\n\n```swift\nclient.streamRequest(StreamingEndpoint())\n    .sink(\n        receiveCompletion: { completion in\n            print(\"Stream completed\")\n        },\n        receiveValue: { (chunk: DataChunk) in\n            print(\"Received chunk: \\(chunk)\")\n        }\n    )\n    .store(in: \u0026cancellables)\n```\n\n### Custom Retry Logic\n\n```swift\nstruct CustomRetryHandler: RetryHandler {\n    let numberOfRetries: Int\n    \n    func shouldRetry(request: URLRequest, error: NetworkError) -\u003e Bool {\n        switch error {\n        case .urlError(let urlError):\n            return urlError.code == .notConnectedToInternet ||\n                   urlError.code == .timedOut\n        case .customError(let statusCode, _):\n            return statusCode \u003e= 500\n        default:\n            return false\n        }\n    }\n    \n    func modifyRequestForRetry(client: APIClient, request: URLRequest, error: NetworkError) -\u003e (URLRequest, NetworkError?) {\n        var newRequest = request\n        newRequest.setValue(\"retry\", forHTTPHeaderField: \"X-Retry-Attempt\")\n        return (newRequest, nil)\n    }\n    \n    // Implement async methods...\n}\n\nlet client = APIClient(retryHandler: CustomRetryHandler(numberOfRetries: 3))\n```\n\n### Authentication\n\n```swift\n// Bearer token authentication\nlet headers = HeaderHandler.shared\n    .addAuthorizationHeader(type: .bearer(token: \"your-token\"))\n    .addAcceptHeaders(type: .applicationJson)\n    .build()\n\nstruct AuthenticatedEndpoint: NetworkRouter {\n    var baseURLString: String { \"https://api.example.com\" }\n    var path: String { \"/protected\" }\n    var method: RequestMethod? { .get }\n    var headers: [String: String]? { headers }\n}\n```\n\n### Network-Aware Operations\n\n```swift\nclass NetworkAwareService {\n    private let client = APIClient()\n    private let monitor = NetworkMonitor()\n    private var pendingRequests: [() -\u003e Void] = []\n    \n    init() {\n        monitor.startMonitoring()\n        setupNetworkHandling()\n    }\n    \n    private func setupNetworkHandling() {\n        monitor.status\n            .sink { [weak self] connectivity in\n                if case .connected = connectivity {\n                    self?.processPendingRequests()\n                }\n            }\n            .store(in: \u0026cancellables)\n    }\n    \n    func makeRequest\u003cT: Codable\u003e(_ endpoint: NetworkRouter) -\u003e AnyPublisher\u003cT, NetworkError\u003e {\n        if case .connected = monitor.currentStatus {\n            return client.request(endpoint)\n        } else {\n            return Future { promise in\n                self.pendingRequests.append {\n                    self.client.request(endpoint)\n                        .sink(receiveCompletion: { promise($0) }, receiveValue: { promise(.success($0)) })\n                        .store(in: \u0026self.cancellables)\n                }\n            }\n            .eraseToAnyPublisher()\n        }\n    }\n}\n```\n\n## Configuration\n\n### Log Levels\n\n```swift\nlet client = APIClient(logLevel: .verbose) // .none, .minimal, .standard, .verbose\n```\n\n### Custom Headers\n\n```swift\nlet headers = HeaderHandler.shared\n    .addContentTypeHeader(type: .applicationJson)\n    .addAcceptHeaders(type: .applicationJson)\n    .addAcceptLanguageHeaders(type: .en)\n    .addAcceptEncodingHeaders(type: .gzip)\n    .addCustomHeader(name: \"X-API-Key\", value: \"your-api-key\")\n    .build()\n```\n\n### VPN Detection\n\n```swift\nlet vpnChecker = VPNChecker()\nif vpnChecker.isVPNActive() {\n    print(\"VPN is connected\")\n    // Handle VPN-specific logic\n}\n```\n\n## Error Handling\n\nThe library provides comprehensive error handling with specific error types:\n\n```swift\nswitch networkError {\ncase .urlError(let urlError):\n    print(\"Network error: \\(urlError.localizedDescription)\")\ncase .decodingError(let decodingError):\n    print(\"Decoding error: \\(decodingError)\")\ncase .customError(let statusCode, let data):\n    print(\"Server error: \\(statusCode)\")\ncase .responseError(let error):\n    print(\"Response error: \\(error)\")\ncase .unknown:\n    print(\"Unknown error occurred\")\n}\n```\n\n## Thread Safety\n\nAll operations in SRNetworkManager are thread-safe:\n\n- **APIClient**: Uses dedicated dispatch queues for synchronization\n- **NetworkMonitor**: Thread-safe status updates and continuation management\n- **HeaderHandler**: Synchronized header operations\n- **UploadProgressDelegate**: Thread-safe progress handling\n\n## Performance Considerations\n\n- **Efficient Monitoring**: Uses system-level network monitoring\n- **Minimal Overhead**: Low CPU and memory usage\n- **Background Operation**: Can operate in background queues\n- **Battery Impact**: Minimal battery impact from monitoring\n\n## Best Practices\n\n### Production Configuration\n\n```swift\n#if DEBUG\nlet logLevel: LogLevel = .verbose\nlet retryHandler = DefaultRetryHandler(numberOfRetries: 3)\n#else\nlet logLevel: LogLevel = .none\nlet retryHandler = DefaultRetryHandler(numberOfRetries: 1)\n#endif\n\nlet client = APIClient(\n    logLevel: logLevel,\n    retryHandler: retryHandler\n)\n```\n\n### Error Handling\n\n```swift\nclient.request(endpoint)\n    .sink(\n        receiveCompletion: { completion in\n            if case .failure(let error) = completion {\n                switch error {\n                case .urlError(let urlError):\n                    if urlError.code == .notConnectedToInternet {\n                        showOfflineMessage()\n                    }\n                case .customError(let statusCode, _):\n                    if statusCode == 401 {\n                        handleUnauthorized()\n                    }\n                default:\n                    showGenericError()\n                }\n            }\n        },\n        receiveValue: { response in\n            handleSuccess(response)\n        }\n    )\n    .store(in: \u0026cancellables)\n```\n\n### Memory Management\n\n```swift\nclass NetworkService {\n    private var cancellables = Set\u003cAnyCancellable\u003e()\n    private let client = APIClient()\n    \n    func makeRequest() {\n        client.request(endpoint)\n            .sink(receiveCompletion: { ... }, receiveValue: { ... })\n            .store(in: \u0026cancellables) // Store to prevent cancellation\n    }\n}\n```\n\n## API Reference\n\n### Core Types\n\n- `APIClient`: Main client for network requests\n- `NetworkRouter`: Protocol for defining API endpoints\n- `NetworkError`: Comprehensive error types\n- `RetryHandler`: Protocol for custom retry logic\n- `NetworkMonitor`: Real-time network monitoring\n- `VPNChecker`: VPN connection detection\n\n### Request Methods\n\n- `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `TRACE`\n\n### Network Types\n\n- `wifi`, `cellular`, `ethernet`, `vpn`, `other`\n\n### Log Levels\n\n- `none`, `minimal`, `standard`, `verbose`\n\n### Content Types\n\n- `applicationJson`, `urlEncoded`, `formData`\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests for new functionality\n5. Ensure all tests pass\n6. Submit a pull request\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Acknowledgments\n\n- Built with Apple's Network framework\n- Inspired by modern networking patterns\n- Designed for performance and reliability\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiamakrostami%2Fsrnetworkmanager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsiamakrostami%2Fsrnetworkmanager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiamakrostami%2Fsrnetworkmanager/lists"}