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
8 changes: 6 additions & 2 deletions .github/workflows/build+test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@ jobs:
- uses: actions/checkout@v2

- name: Build package
run: swift build -v
run: |
xcodes select 26.1.1
swift build -v

test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2

- name: Smoke test package
run: swift test -v
run: |
xcodes select 26.1.1
swift test -v

- name: CINotify Email
if: ${{ failure() }}
Expand Down
5 changes: 2 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// swift-tools-version:6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
// swift-tools-version:6.2

import PackageDescription

let package = Package(
name: "ScryfallKit",
platforms: [.macOS(.v10_13), .iOS(.v12)],
platforms: [.macOS(.v11), .iOS(.v14), .watchOS(.v11), .visionOS(.v26), .tvOS(.v14)],
products: [
.library(
name: "ScryfallKit",
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ client.getCardByName(exact: "Doom Blade", set: "STA") { result in
```

## Network Logging
The ScryfallClient has a configurable level of network logging with two options: minimal and verbose. Enabling verbose logging will print the HTTP body of each request and response. Minimal logging will log that a request was made (and the URL it's made to) as well as that a response was received.
The ScryfallClient will emit trace and debug logs if supplied with an `Logger` instance from the `OSLog` library.

## Contributing
Contributions are always welcome, simply fork this repo, make and test your changes, and then open a pull request. I will try and review it within a reasonable amount of time.
5 changes: 0 additions & 5 deletions Sources/ScryfallKit/Extensions/Card+helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,6 @@ extension Card {
}

guard let uri = uris.uri(for: type) else {
if #available(iOS 14.0, macOS 11.0, *) {
Logger.main.error("No URI for image type \(type.rawValue)")
} else {
print("No URI for image type \(type)")
}
return nil
}

Expand Down
16 changes: 0 additions & 16 deletions Sources/ScryfallKit/Logger.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,6 @@ struct GetCard: EndpointRequest {
default:
// This guard should never trip. The only card identifier that doesn't have provider/id is the set code/collector
guard let id = identifier.id else {
if #available(iOS 14.0, macOS 11.0, *) {
Logger.main.error("Provided identifier doesn't have a provider or doesn't have an id")
} else {
print("Provided identifier doesn't have a provider or doesn't have an id")
}

fatalError(
"Encountered a situation that shouldn't be possible: Card identifier's id property was nil"
)
Expand All @@ -121,14 +115,6 @@ struct GetCardCollection: EndpointRequest {
let identifierJSON = identifiers.map { $0.json }
let requestBody: [String: [[String: String]]] = ["identifiers": identifierJSON]

do {
body = try JSONSerialization.data(withJSONObject: requestBody)
} catch {
if #available(iOS 14.0, macOS 11.0, *) {
Logger.main.error("Errored serializing dict to JSON for GetCardCollection request")
} else {
print("Errored serializing dict to JSON for GetCardCollection request")
}
}
self.body = try? JSONSerialization.data(withJSONObject: requestBody)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ extension EndpointRequest {
}

guard let url = urlComponents?.url else {
if #available(iOS 14.0, macOS 11.0, *) {
Logger.main.error("Couldn't make url")
} else {
print("Couldn't make url")
}
return nil
}

Expand Down
54 changes: 11 additions & 43 deletions Sources/ScryfallKit/Networking/NetworkService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,52 +5,33 @@
import Foundation
import OSLog

/// An enum representing the two available levels of log verbosity
public enum NetworkLogLevel: Sendable {
/// Only log when requests are made and errors
case minimal
/// Log the bodies of requests and responses
case verbose
}

protocol NetworkServiceProtocol: Sendable {
func request<T: Decodable>(
_ request: EndpointRequest,
as type: T.Type,
completion: @Sendable @escaping (Result<T, Error>) -> Void
)
@available(macOS 10.15.0, *, iOS 13.0.0, *)
func request<T: Decodable>(_ request: EndpointRequest, as type: T.Type) async throws -> T
}

struct NetworkService: NetworkServiceProtocol, Sendable {
var logLevel: NetworkLogLevel
let logger: Logger?

func request<T: Decodable>(
init(logger: Logger?) {
self.logger = logger
}

func request<T: Decodable & Sendable>(
_ request: EndpointRequest, as type: T.Type,
completion: @Sendable @escaping (Result<T, Error>) -> Void
) {
guard let urlRequest = request.urlRequest else {
if #available(macOS 11.0, iOS 14.0, *) {
Logger.network.error("Invalid url request")
} else {
print("Invalid url request")
}
logger?.error("Invalid url request")
completion(.failure(ScryfallKitError.invalidUrl))
return
}

if logLevel == .verbose, let body = urlRequest.httpBody,
let JSONString = String(data: body, encoding: String.Encoding.utf8)
{
print("Sending request with body:")
if #available(macOS 11.0, iOS 14.0, *) {
Logger.network.debug("\(JSONString)")
} else {
print(JSONString)
}
}

logger?.trace("Starting request: \(urlRequest.debugDescription)")
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
do {
let result = try handle(dataType: type, data: data, response: response, error: error)
Expand All @@ -60,12 +41,7 @@ struct NetworkService: NetworkServiceProtocol, Sendable {
}
}

if #available(macOS 11.0, iOS 14.0, *) {
Logger.network.debug(
"Making request to: '\(String(describing: urlRequest.url?.absoluteString))'")
} else {
print("Making request to: '\(String(describing: urlRequest.url?.absoluteString))'")
}
logger?.trace("Making request to: '\(String(describing: urlRequest.url?.absoluteString))'")
task.resume()
}

Expand All @@ -88,23 +64,15 @@ struct NetworkService: NetworkServiceProtocol, Sendable {
decoder.keyDecodingStrategy = .convertFromSnakeCase

if (200..<300).contains(httpStatus) {
if logLevel == .verbose {
let responseBody = String(data: content, encoding: .utf8)
if #available(macOS 11.0, iOS 14.0, *) {
Logger.network.debug("\(responseBody ?? "Couldn't represent response body as string")")
} else {
print(responseBody ?? "Couldn't represent response body as string")
}
}

let responseBody = String(data: content, encoding: .utf8)
logger?.debug("\(responseBody ?? "Couldn't represent response body as string")")
return try decoder.decode(dataType, from: content)
} else {
let httpError = try decoder.decode(ScryfallError.self, from: content)
throw ScryfallKitError.scryfallError(httpError)
}
}

@available(macOS 10.15.0, *, iOS 13.0.0, *)
func request<T: Decodable>(_ request: EndpointRequest, as type: T.Type) async throws -> T
where T: Sendable {
try await withCheckedThrowingContinuation { continuation in
Expand Down
1 change: 0 additions & 1 deletion Sources/ScryfallKit/ScryfallClient+Async.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import Foundation

@available(macOS 10.15.0, *, iOS 13.0.0, *)
extension ScryfallClient {
/// Equivalent to ``searchCards(filters:unique:order:sortDirection:includeExtras:includeMultilingual:includeVariations:page:completion:)`` but with async/await syntax
public func searchCards(
Expand Down
9 changes: 4 additions & 5 deletions Sources/ScryfallKit/ScryfallClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@
//

import Foundation
import OSLog

/// A client for interacting with the Scryfall API
public final class ScryfallClient: Sendable {
private let networkLogLevel: NetworkLogLevel
let networkService: NetworkServiceProtocol

/// Initialize an instance of the ScryfallClient
/// - Parameter networkLogLevel: The desired logging level. See ``NetworkLogLevel``
public init(networkLogLevel: NetworkLogLevel = .minimal) {
self.networkLogLevel = networkLogLevel
self.networkService = NetworkService(logLevel: networkLogLevel)
/// - Parameter logger: The logger to use. Pass nil to disable logging
public init(logger: Logger? = nil) {
self.networkService = NetworkService(logger: logger)
}

/// Perform a search using an array of ``CardFieldFilter`` objects.
Expand Down
6 changes: 3 additions & 3 deletions Tests/ScryfallKitTests/SmokeTests.swift
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
//
// SmokeTests.swift
//

import OSLog
import XCTest

@testable import ScryfallKit

@available(iOS 13.0.0, *)
final class SmokeTests: XCTestCase {
var client: ScryfallClient!

override func setUp() {
self.client = ScryfallClient()
let logger = Logger(subsystem: "dev.hearst.ScryfallKitTests", category: "SmokeTests")
self.client = ScryfallClient(logger: logger)
}

func testLayouts() async throws {
Expand Down