From a00215635eb4605650c2b59f2ca4e742bec95469 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sun, 8 Sep 2024 23:54:25 +0200 Subject: [PATCH] Implemented the AmiiboLiveClient client in the package target. --- Sources/Public/Clients/AmiiboLiveClient.swift | 235 ++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 Sources/Public/Clients/AmiiboLiveClient.swift diff --git a/Sources/Public/Clients/AmiiboLiveClient.swift b/Sources/Public/Clients/AmiiboLiveClient.swift new file mode 100644 index 0000000..9920df1 --- /dev/null +++ b/Sources/Public/Clients/AmiiboLiveClient.swift @@ -0,0 +1,235 @@ +//===----------------------------------------------------------------------=== +// +// This source file is part of the AmiiboAPI open source project +// +// Copyright (c) 2024 Röck+Cöde VoF. and the AmiiboAPI project authors +// Licensed under the EUPL 1.2 or later. +// +// See LICENSE for license information +// See CONTRIBUTORS for the list of AmiiboAPI project authors +// +//===----------------------------------------------------------------------=== + +import Foundation +import OpenAPIURLSession + +public struct AmiiboLiveClient { + + // MARK: Properties + + private let client: Client + + // MARK: Initialisers + + public init() throws { + self.client = .init( + serverURL: try Servers.server1(), + configuration: .init(dateTranscoder: ISODateTranscoder()), + transport: URLSessionTransport() + ) + } + +} + +// MARK: - APIProtocol + +extension AmiiboLiveClient: APIClient { + + // MARK: Functions + + public func getAmiibos(by filter: AmiiboFilter) async throws -> [Amiibo] { + let response = try await client.getAmiibos( + .init(query: .init( + amiiboSeries: filter.series, + character: filter.gameCharacter, + gameseries: filter.gameSeries, + id: filter.identifier, + name: filter.name, + showgames: filter.showGames, + showusage: filter.showUsage, + _type: filter.type + )) + ) + + switch response { + case let .ok(ok): + switch ok.body { + case let .json(output): + return map(output) + } + + case .badRequest: + throw AmiiboServiceError.badRequest + + case let .undocumented(statusCode, _): + throw AmiiboServiceError.undocumented(statusCode) + } + } + + public func getAmiiboSeries(by filter: AmiiboSeriesFilter) async throws -> [AmiiboSeries] { + let response = try await client.getAmiiboSeries( + .init(query: .init( + key: filter.key, + name: filter.name + )) + ) + + switch response { + case let .ok(ok): + switch ok.body { + case let .json(output): + return map(output, as: AmiiboSeries.self) + } + + case .badRequest: + throw AmiiboServiceError.badRequest + + case .internalServerError: + throw AmiiboServiceError.notAvailable + + case .notFound: + throw AmiiboServiceError.notFound + + case let .undocumented(statusCode, _): + throw AmiiboServiceError.undocumented(statusCode) + } + } + + public func getAmiiboTypes(by filter: AmiiboTypeFilter) async throws -> [AmiiboType] { + let response = try await client.getAmiiboTypes( + .init(query: .init( + key: filter.key, + name: filter.name + )) + ) + + switch response { + case let .ok(ok): + switch ok.body { + case let .json(output): + return map(output, as: AmiiboType.self) + } + + case .badRequest: + throw AmiiboServiceError.badRequest + + case .internalServerError: + throw AmiiboServiceError.notAvailable + + case .notFound: + throw AmiiboServiceError.notFound + + case let .undocumented(statusCode, _): + throw AmiiboServiceError.undocumented(statusCode) + } + } + + public func getGameCharacters(by filter: GameCharacterFilter) async throws -> [GameCharacter] { + let response = try await client.getGameCharacters( + .init(query: .init( + key: filter.key, + name: filter.name + )) + ) + + switch response { + case let .ok(ok): + switch ok.body { + case let .json(output): + return map(output, as: GameCharacter.self) + } + + case .badRequest: + throw AmiiboServiceError.badRequest + + case .internalServerError: + throw AmiiboServiceError.notAvailable + + case .notFound: + throw AmiiboServiceError.notFound + + case let .undocumented(statusCode, _): + throw AmiiboServiceError.undocumented(statusCode) + } + } + + public func getGameSeries(by filter: GameSeriesFilter) async throws -> [GameSeries] { + let response = try await client.getGameSeries( + .init(query: .init( + key: filter.key, + name: filter.name + )) + ) + + switch response { + case let .ok(ok): + switch ok.body { + case let .json(output): + return map(output, as: GameSeries.self) + } + + case .badRequest: + throw AmiiboServiceError.badRequest + + case .internalServerError: + throw AmiiboServiceError.notAvailable + + case .notFound: + throw AmiiboServiceError.notFound + + case let .undocumented(statusCode, _): + throw AmiiboServiceError.undocumented(statusCode) + } + } + + public func getLastUpdated() async throws -> Date { + let response = try await client.getLastUpdated() + + switch response { + case let .ok(ok): + switch ok.body { + case let .json(output): + return output.lastUpdated + } + + case let .undocumented(statusCode, _): + throw AmiiboServiceError.undocumented(statusCode) + } + } + +} + +// MARK: - Helpers + +private extension AmiiboLiveClient { + + // MARK: Functions + + func map(_ wrapper: Components.Schemas.AmiiboWrapper) -> [Amiibo] { + switch wrapper.amiibo { + case let .Amiibo(object): + return [.init(object)] + + case let .AmiiboList(list): + return list + .map { .init($0) } + .sorted { $0.identifier < $1.identifier } + } + } + + func map( + _ wrapper: Components.Schemas.TupleWrapper, + as: Model.Type + ) -> [Model] { + switch wrapper.amiibo { + case let .Tuple(payload): + return [.init(payload)] + + case let .TupleList(list): + return list + .map { .init($0) } + .sorted { $0.key < $1.key } + } + } + +}