Skip to content

Commit

Permalink
Merge pull request #10 from pawello2222/dev
Browse files Browse the repository at this point in the history
Release 2.0.0
  • Loading branch information
pawello2222 authored May 19, 2024
2 parents 2d685e7 + 719d54a commit 6f6c6ad
Show file tree
Hide file tree
Showing 81 changed files with 3,590 additions and 352 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: SwiftLint
uses: norio-nomura/action-swiftlint@3.2.1

test:
runs-on: macos-13
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Test
run: |
swift test --enable-code-coverage
xcrun llvm-cov report $BUILD_FOLDER -instr-profile $PROFDATA_FOLDER
xcrun llvm-cov export -format="lcov" $BUILD_FOLDER -instr-profile $PROFDATA_FOLDER > $LCOV_PATH
- name: Upload Coverage Data
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ${{ env.LCOV_PATH }}
Expand Down
58 changes: 47 additions & 11 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,32 +1,68 @@
// swift-tools-version: 5.7
// swift-tools-version: 5.9

import PackageDescription

let package = Package(
name: "PhantomKit",
platforms: [
.iOS(.v16),
.macOS(.v13),
.watchOS(.v9),
.tvOS(.v16)
.iOS(.v17),
.macOS(.v14),
.watchOS(.v10),
.tvOS(.v17)
],
products: [
.library(
name: "PhantomKit",
targets: ["PhantomKit"]
name: "PhantomKitAPI",
targets: ["PhantomKitAPI"]
),
.library(
name: "PhantomKitCore",
targets: ["PhantomKitCore"]
),
.library(
name: "PhantomKitLog",
targets: ["PhantomKitLog"]
),
.library(
name: "PhantomKitUI",
targets: ["PhantomKitUI"]
)
],
dependencies: [
.package(url: "https://github.com/pawello2222/Appliable", from: "1.0.0")
.package(url: "https://github.com/pawello2222/Appliable", .upToNextMajor(from: "1.0.0"))
],
targets: [
.target(
name: "PhantomKit",
name: "PhantomKitAPI",
dependencies: ["PhantomKitCore", "PhantomKitLog"]
),
.target(
name: "PhantomKitCore",
dependencies: ["Appliable"]
),
.target(
name: "PhantomKitLog",
dependencies: ["Appliable"]
),
.target(
name: "PhantomKitUI",
dependencies: ["PhantomKitCore"]
),
.testTarget(
name: "PhantomKitAPITests",
dependencies: ["PhantomKitAPI"]
),
.testTarget(
name: "PhantomKitCoreTests",
dependencies: ["PhantomKitCore"]
),
.testTarget(
name: "PhantomKitLogTests",
dependencies: ["PhantomKitCore", "PhantomKitLog"]
),
.testTarget(
name: "PhantomKitTests",
dependencies: ["PhantomKit"]
name: "PhantomKitUITests",
dependencies: ["PhantomKitUI"]
)
]
)
28 changes: 7 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,15 @@
<img src=".resources/Assets/logo.png" alt="PhantomKit logo" height=150>
</p>
<p align="center">
<a href="https://github.com/pawello2222/PhantomKit/actions?query=branch%3Amain">
<img src="https://img.shields.io/github/actions/workflow/status/pawello2222/PhantomKit/ci.yml?logo=github" alt="Build">
</a>
<a href="https://codecov.io/gh/pawello2222/PhantomKit">
<img src="https://codecov.io/gh/pawello2222/PhantomKit/branch/main/graph/badge.svg?token=TFHOHUXCVJ" alt="Code coverage">
</a>
<a href="https://github.com/pawello2222/PhantomKit">
<img src="https://img.shields.io/badge/language-swift-orange.svg" alt="Language">
</a>
<a href="https://github.com/pawello2222/PhantomKit#installation">
<img src="https://img.shields.io/badge/platform-iOS%20%7C%20macOS%20%7C%20watchOS%20%7C%20tvOS-lightgrey.svg" alt="Supported platforms">
</a>
<a href="https://github.com/pawello2222/PhantomKit/actions?query=branch%3Amain"><img src="https://img.shields.io/github/actions/workflow/status/pawello2222/PhantomKit/ci.yml?logo=github" alt="Build"></a>
<a href="https://codecov.io/gh/pawello2222/PhantomKit"><img src="https://codecov.io/gh/pawello2222/PhantomKit/branch/main/graph/badge.svg?token=TFHOHUXCVJ" alt="Code coverage"></a>
<a href="https://github.com/pawello2222/PhantomKit"><img src="https://img.shields.io/badge/language-swift-orange.svg" alt="Language"></a>
<a href="https://github.com/pawello2222/PhantomKit#installation"><img src="https://img.shields.io/badge/platform-iOS%20%7C%20macOS%20%7C%20watchOS%20%7C%20tvOS-lightgrey.svg" alt="Supported platforms"></a>
</p>
<p align="center">
<a href="https://github.com/pawello2222/PhantomKit#installation">
<img src="https://img.shields.io/badge/SPM-compatible-brightgreen.svg" alt="Swift Package Manager">
</a>
<a href="https://github.com/pawello2222/PhantomKit/releases">
<img src="https://img.shields.io/github/v/release/pawello2222/PhantomKit" alt="Release version">
</a>
<a href="https://github.com/pawello2222/PhantomKit/blob/main/LICENSE.md">
<img src="https://img.shields.io/github/license/pawello2222/PhantomKit" alt="License">
</a>
<a href="https://github.com/pawello2222/PhantomKit#installation"><img src="https://img.shields.io/badge/SPM-compatible-brightgreen.svg" alt="Swift Package Manager"></a>
<a href="https://github.com/pawello2222/PhantomKit/releases"><img src="https://img.shields.io/github/v/release/pawello2222/PhantomKit" alt="Release version"></a>
<a href="https://github.com/pawello2222/PhantomKit/blob/main/LICENSE.md"><img src="https://img.shields.io/github/license/pawello2222/PhantomKit" alt="License"></a>
</p>

# PhantomKit
Expand Down
39 changes: 39 additions & 0 deletions Sources/PhantomKitAPI/API/APIDataSource.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// The MIT License (MIT)
//
// Copyright (c) 2024-Present Paweł Wiszenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Foundation

public protocol APIDataSource: NetworkDataSource {
associatedtype Endpoint: APIEndpoint
}

// MARK: - Common

extension APIDataSource {
public func call(
endpoint: Endpoint,
allowedHTTPCodes: HTTPCodes = .success
) async throws -> Data {
let request = try endpoint.urlRequest()
return try await call(request: request, allowedHTTPCodes: allowedHTTPCodes)
}
}
48 changes: 48 additions & 0 deletions Sources/PhantomKitAPI/API/APIEndpoint.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// The MIT License (MIT)
//
// Copyright (c) 2024-Present Paweł Wiszenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Appliable
import Foundation
import PhantomKitCore

public protocol APIEndpoint {
var baseURL: String { get }
var path: String { get }
var method: APIMethod { get }
var headers: [String: String]? { get }
func body() throws -> Data?
}

// MARK: - Common

extension APIEndpoint {
public func urlRequest() throws -> URLRequest {
guard let url = URL(string: baseURL)?.appending(component: path) else {
throw APIError.invalidURL
}
return try URLRequest(url: url).applying {
$0.httpMethod = method.rawValue
$0.allHTTPHeaderFields = headers
$0.httpBody = try body()
}
}
}
107 changes: 107 additions & 0 deletions Sources/PhantomKitAPI/Core/NetworkDataSource.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// The MIT License (MIT)
//
// Copyright (c) 2024-Present Paweł Wiszenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Foundation
import PhantomKitCore
import PhantomKitLog

public protocol NetworkDataSource {
var session: NetworkSession { get }
var logger: Logger? { get }
}

// MARK: - Common

extension NetworkDataSource {
public func call(
request: URLRequest,
allowedHTTPCodes: HTTPCodes = .success
) async throws -> Data {
do {
log(request: request)
let (data, response) = try await session.data(for: request)
guard let response = response as? HTTPURLResponse else {
throw APIError.unexpectedResponse(response)
}
log(request: request, response: response, data: data)
guard allowedHTTPCodes ~= response.statusCode else {
throw APIError.httpCode(response.statusCode, message: nil)
}
return data
} catch let error as URLError {
throw try map(error: error)
}
}

private func map(error: URLError) throws -> Error {
guard error.code.isConnectionError else {
return error
}
return APIError.connectionError
}
}

// MARK: - Logger

extension NetworkDataSource {
private func log(request: URLRequest) {
guard let logger else {
return
}
let httpMethod = request.httpMethod ?? "?"
logger.debug(
"[\(httpMethod)] --> \(request)",
category: DefaultLogCategory.default
)
}

private func log(request: URLRequest, response: HTTPURLResponse, data: Data) {
guard let logger else {
return
}
let httpMethod = request.httpMethod ?? "?"
let body = String(data: data, encoding: .utf8) ?? ""
logger.debug(
"[\(httpMethod)] \(response.statusCode) \(request)\n\(body)",
category: DefaultLogCategory.default
)
}
}

// MARK: - URLError.Code

extension URLError.Code {
fileprivate var isConnectionError: Bool {
isContained(
in: [
.cannotConnectToHost,
.cannotFindHost,
.cannotLoadFromNetwork,
.internationalRoamingOff,
.networkConnectionLost,
.notConnectedToInternet,
.secureConnectionFailed,
.timedOut
]
)
}
}
42 changes: 42 additions & 0 deletions Sources/PhantomKitAPI/Core/NetworkSession.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// The MIT License (MIT)
//
// Copyright (c) 2024-Present Paweł Wiszenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Foundation

public protocol NetworkSession {
func data(
for urlRequest: URLRequest,
delegate: URLSessionTaskDelegate?
) async throws -> (Data, URLResponse)
}

// MARK: - Common

extension NetworkSession {
public func data(for request: URLRequest) async throws -> (Data, URLResponse) {
try await data(for: request, delegate: nil)
}
}

// MARK: - URLSession

extension URLSession: NetworkSession {}
Loading

0 comments on commit 6f6c6ad

Please sign in to comment.