{"id":20684072,"url":"https://github.com/silkodenis/swift-combine-networking","last_synced_at":"2025-03-10T21:52:21.849Z","repository":{"id":238905707,"uuid":"796928995","full_name":"silkodenis/swift-combine-networking","owner":"silkodenis","description":"A Swift package for declarative HTTP networking with the Combine framework, designed for easy configuration and robust error handling.","archived":false,"fork":false,"pushed_at":"2024-09-06T12:48:30.000Z","size":77,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-17T16:14:42.843Z","etag":null,"topics":["api","client","combine","declarative","http","http-client","mock","networking","request-builder","spm","swift","swift-package-manager"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/silkodenis.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-05-06T22:09:17.000Z","updated_at":"2024-09-06T12:48:33.000Z","dependencies_parsed_at":"2024-05-08T22:44:05.104Z","dependency_job_id":"3ebb8bee-e88a-467e-a458-58f638244983","html_url":"https://github.com/silkodenis/swift-combine-networking","commit_stats":null,"previous_names":["silkodenis/combine-networking","silkodenis/swift-combine-networking"],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silkodenis%2Fswift-combine-networking","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silkodenis%2Fswift-combine-networking/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silkodenis%2Fswift-combine-networking/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/silkodenis%2Fswift-combine-networking/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/silkodenis","download_url":"https://codeload.github.com/silkodenis/swift-combine-networking/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242933887,"owners_count":20208912,"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":["api","client","combine","declarative","http","http-client","mock","networking","request-builder","spm","swift","swift-package-manager"],"created_at":"2024-11-16T22:18:56.378Z","updated_at":"2025-03-10T21:52:21.824Z","avatar_url":"https://github.com/silkodenis.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![License](https://img.shields.io/github/license/silkodenis/swift-combine-networking.svg)](https://github.com/silkodenis/swift-combine-networking/blob/main/LICENSE)\n![swift](https://github.com/silkodenis/swift-combine-networking/actions/workflows/swift.yml/badge.svg?branch=main)\n\n# Combine Networking\n\nCombineNetworking is a robust and flexible HTTP networking package for Swift, designed to leverage the Combine framework for handling network requests in a declarative way. This package simplifies the process of making HTTP requests, decoding responses, and handling errors.\n\n## Core Features\n\n- **Flexible and Declarative Networking**: Use Swift enums and protocols to define and configure various network operations, simplifying and clarifying the setup of HTTP requests.\n- **Combine Integration**: Take full advantage of Swift's Combine framework for managing asynchronous network requests and handling responses.\n- **Mockable HTTP Sessions**: Provides the ability to mock HTTP sessions, which is crucial for unit testing and ensuring that your application behaves as expected under various network conditions without relying on live network calls.\n- **Robust Error Handling**: Includes comprehensive error handling mechanisms to manage and respond to different network and decoding errors effectively.\n\n\n## Installation\n\n### Requirements\n\n- **Swift 5.1**+\n- **Xcode 11**+\n- **iOS**: iOS 13.0+\n- **macOS**: macOS 10.15+\n- **watchOS**: watchOS 6.0+\n- **tvOS**: tvOS 13.0+\n\n### Using Swift Package Manager from Xcode\nTo add CombineNetworking to your project in Xcode:\n1. Open your project in Xcode.\n2. Navigate to `File` → `Swift Packages` → `Add Package Dependency...`.\n3. Paste the repository URL: `https://github.com/silkodenis/swift-combine-networking.git`.\n4. Choose the version you want to use (you can specify a version, a commit, or a branch).\n5. Click `Next` and Xcode will download the package and add it to your project.\n\n## Components\n\n- **[HTTPSession](https://github.com/silkodenis/swift-combine-networking/blob/main/Sources/CombineNetworking/HTTPSession.swift) Protocol**: Allows for mocking of session behavior in unit tests, making it easier to test network interactions.\n- **[HTTPEndpoint](https://github.com/silkodenis/swift-combine-networking/blob/main/Sources/CombineNetworking/HTTPEndpoint.swift) Protocol**: Facilitates the construction of different HTTP requests using a clear and concise interface.\n- **[HTTPRequestBuilder](https://github.com/silkodenis/swift-combine-networking/blob/main/Sources/CombineNetworking/HTTPRequestBuilder.swift)**: Provides a declarative API for building URL requests from HTTPEndpoint instances.\n- **[HTTPClient](https://github.com/silkodenis/swift-combine-networking/blob/main/Sources/CombineNetworking/HTTPClient.swift)**: Executes network requests and processes the responses, supporting generic decoding.\n- **[HTTPClientError](https://github.com/silkodenis/swift-combine-networking/blob/main/Sources/CombineNetworking/HTTPClient.swift)**: Manages error states that can occur during the execution of HTTP requests. This enumeration helps in categorizing and handling different types of errors, such as:\n  - **invalidResponse**: Indicates that the HTTP response was not valid or did not meet expected criteria, containing details about the response.\n  - **decodingError**: Occurs when there is a failure in decoding the response data, providing the underlying error for more context.\n  - **networkError**: Represents errors related to network connectivity issues or problems with the network request itself.\n  \n## Usage\nHere’s how to use CombineNetworking in your project:\n\n\u003cdetails\u003e\n\u003csummary\u003eDefine an Endpoint\u003c/summary\u003e\n    \nFirst, define your endpoints using the HTTPEndpoint protocol:\n\n```swift\nenum Endpoint {\n    case createUser\n    case fetchUser(id: Int)\n    case updateUser(id: Int)\n    case deleteUser(id: Int)\n}\n\nextension Endpoint: HTTPEndpoint {\n    var baseURL: URL {\n        return URL(string: \"https://api.example.com\")!\n    }\n    \n    var path: String {\n        switch self {\n        case .createUser:\n            return \"/users\"\n        case .fetchUser(let id), .updateUser(let id), .deleteUser(let id):\n            return \"/users/\\(id)\"\n        }\n    }\n    \n    var method: HTTPMethod {\n        switch self {\n        case .createUser:\n            return .post\n        case .fetchUser:\n            return .get\n        case .updateUser:\n            return .put\n        case .deleteUser:\n            return .delete\n        }\n    }\n    \n    var headers: [String: String]? {\n        return [\"Content-Type\": \"application/json\"]\n    }\n    \n    var parameters: [String: Any]? {\n        switch self {\n        case .createUser, .updateUser:\n            return [\"param\": \"value\"]  // Example parameters.\n        default:\n            return nil\n        }\n    }\n    \n    var timeout: TimeInterval {\n        return 30\n    }\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eCreate and Execute a Request\u003c/summary\u003e\n    \n```swift\nstruct UserDataDTO: Codable {\n    let name: String\n}\n\nlet builder = HTTPRequestBuilder\u003cEndpoint\u003e(jsonEncoder: JSONEncoder())\nlet client = HTTPClient(jsonDecoder: JSONDecoder(), session: URLSession.shared)\n\nfunc fetchUser(id: Int) -\u003e AnyPublisher\u003cUserDataDTO, Error\u003e {\n        builder.request(.fetchUser(id: id))\n            .flatMap(client.executeJsonRequest)\n            .eraseToAnyPublisher()\n}\n```\n\nReplace `UserDataDTO` with the appropriate data model expected from the API. Ensure that this model conforms to the `Codable` protocol, which enables it to be easily decoded from JSON or encoded to JSON, depending on your needs.\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n\u003csummary\u003eError Handling\u003c/summary\u003e\nHere's how you might call fetchUser and handle various potential errors:\n  \n```swift\nfetchUser(id: 123)\n    .sink(receiveCompletion: { completion in\n        switch completion {\n        case .finished:\n            print(\"Fetch completed successfully.\")\n        case .failure(let error):\n            switch error {\n            case let HTTPClientError.invalidResponse(details):\n                print(\"Invalid response: Status code \\(details.statusCode). Description: \\(details.description ?? \"No description\")\")\n            case let HTTPClientError.decodingError(decodingError):\n                print(\"Decoding error: \\(decodingError.localizedDescription)\")\n            case let HTTPClientError.networkError(networkError):\n                print(\"Network error: \\(networkError.localizedDescription)\")\n            default:\n                print(\"An unexpected error occurred: \\(error.localizedDescription)\")\n            }\n        }\n    }, receiveValue: { userData in\n        print(\"Received user data: \\(userData)\")\n    })\n    .store(in: \u0026cancellables)\n```\n\n### Understanding the Errors\n- **Invalid Response**: Occurs when the server's response doesn't meet the expected criteria, such as an incorrect status code or malformed headers.\n- **Decoding Error**: Happens if the JSONDecoder cannot decode the response data into the expected UserDataDTO format.\n- **Network Error**: Includes all errors related to connectivity issues, such as timeouts or lack of internet connection.\nThis approach ensures that your application can gracefully handle different error scenarios, providing a better user experience by dealing with errors appropriately.\n\n\u003c/details\u003e\n  \n\u003cdetails\u003e\n\u003csummary\u003eMocking HTTPSession for Testing\u003c/summary\u003e\nYou can create a mock session that simulates network responses for testing. This approach is beneficial for unit tests where you want to control the inputs and outputs strictly:\n\n```swift\nstruct MockSession: HTTPSession {\n    func dataTask(for request: URLRequest) -\u003e AnyPublisher\u003cHTTPResponse, URLError\u003e {\n        return Fail(error: URLError(.notConnectedToInternet)).eraseToAnyPublisher()\n    }\n}\n\n// Example of using a mock session:\nlet mock = HTTPClient(jsonDecoder: JSONDecoder(), session: MockSession())\nlet real = HTTPClient(jsonDecoder: JSONDecoder(), session: URLSession.shared)\n```\n\n\u003c/details\u003e\n\n## Examples\n- [MoviesAPI Service](https://github.com/silkodenis/swift-combine-networking/tree/main/Examples/MoviesAPI)\n- [SwiftUI App](https://github.com/silkodenis/swiftui-moviesdb-redux-app)\n\n## Contributing\n\nContributions are welcome! Feel free to open issues or submit pull requests.\n\n## License\nThis project is licensed under the [Apache License, Version 2.0](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsilkodenis%2Fswift-combine-networking","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsilkodenis%2Fswift-combine-networking","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsilkodenis%2Fswift-combine-networking/lists"}