From 0b000af54318a528eea046349b734ba3bfdac923 Mon Sep 17 00:00:00 2001 From: Bill Panagiotopoulos Date: Mon, 20 Mar 2023 21:54:12 +0200 Subject: [PATCH] Name refactor to align with the Repository pattern (35) --- .github/workflows/main.yml | 4 +- Examples/Communication/DemoEnvironment.swift | 2 +- .../ServiceErrorInterceptor.swift | 2 +- .../Middleware/CryptoMiddleware.swift | 2 +- .../Communication/Models/Domain/City.swift | 2 +- .../Models/Domain/EncryptedModel.swift | 2 +- .../Models/Domain/FileResponse.swift | 2 +- .../Communication/Models/Rest/RSCity.swift | 2 +- .../Models/Rest/RSEncryptedModel.swift | 2 +- .../Models/Rest/RSFileResponse.swift | 2 +- .../CitiesRepository.swift} | 43 +++--- .../MiscRepository.swift} | 12 +- .../Transformers/CitiesTransformer.swift | 2 +- .../Transformers/CityTransformer.swift | 2 +- .../EncryptedModelTransformer.swift | 2 +- .../Transformers/FileUploadTransformer.swift | 2 +- Examples/Screens/AppDelegate.swift | 2 +- .../City Explorer/CityExplorerDetails.swift | 26 +--- .../City Explorer/CityExplorerView.swift | 30 +--- Examples/Screens/ContentView.swift | 2 +- Examples/Screens/DemoApp.swift | 6 +- .../EncryptedCommunicationView.swift | 4 +- .../File Downloader/FileDownloader.swift | 2 +- .../Screens/File Uploader/FileUploader.swift | 4 +- .../File Uploader/FileUploaderUtils.swift | 2 +- .../Pinning/CertificatePinningView.swift | 4 +- .../Screens/Reachability/Reachability.swift | 2 +- .../Screens/TermiNetworkExamplesApp.swift | 2 +- Examples/Screens/UIHelpers.swift | 2 +- Package.swift | 6 +- README.md | 107 ++++++------- Source/Cache.swift | 2 +- Source/CertificatePinningManager.swift | 2 +- Source/{Router.swift => Client.swift} | 16 +- Source/Configuration.swift | 13 +- ...tion.swift => EndpointConfiguration.swift} | 14 +- Source/Environment.swift | 4 +- Source/Extensions/Data+Extensions.swift | 2 +- Source/Extensions/Dictionary+Extensions.swift | 2 +- .../Operations/Decodable+Transformer.swift | 2 +- .../Operations/Request+DataOperations.swift | 2 +- .../Operations/Request+FileOperations.swift | 2 +- .../Request+FileOperationsAsync.swift | 2 +- Source/Extensions/Request+Async.swift | 2 +- Source/Extensions/Request+Interceptors.swift | 2 +- Source/Extensions/Request+Middleware.swift | 2 +- Source/Extensions/Request+Mock.swift | 2 +- Source/Extensions/Request+NSCopying.swift | 2 +- .../Extensions/Request+ResponseHeaders.swift | 2 +- Source/Extensions/Request+ResponseTypes.swift | 2 +- Source/Extensions/UIImage+Extensions.swift | 2 +- .../Extensions/UIImageView+Extensions.swift | 2 +- Source/Extensions/URLRequest+Extensions.swift | 2 +- Source/FileStreamer.swift | 2 +- Source/Helpers/MultipartFormDataHelpers.swift | 2 +- Source/Helpers/RequestBodyGenerators.swift | 2 +- Source/Helpers/RequestHelpers.swift | 2 +- Source/Log.swift | 129 ++++++++-------- Source/MultipartFormDataPartType.swift | 2 +- Source/MultipartFormDataStream.swift | 2 +- Source/Operation.swift | 2 +- Source/Path.swift | 2 +- ...eProtocol.swift => EndpointProtocol.swift} | 15 +- Source/Protocols/InterceptorProtocol.swift | 2 +- .../Protocols/RequestMiddlewareProtocol.swift | 2 +- Source/Queue.swift | 2 +- Source/Reachability.swift | 2 +- Source/Request.swift | 38 +++-- Source/Session.swift | 2 +- Source/SessionTaskFactory.swift | 2 +- Source/SwiftUI/Image.swift | 2 +- Source/TNError.swift | 6 +- Source/Types.swift | 2 +- TermiNetwork.xcodeproj/project.pbxproj | 58 ++++---- TermiNetwork/TermiNetwork.h | 2 +- Tests/CryptoMiddleware.swift | 2 +- Tests/DoNothingInterceptor.swift | 2 +- Tests/Env.swift | 2 +- Tests/GlobalInterceptor.swift | 2 +- .../{main-router => main-repo}/headers.json | 0 Tests/Models/Domain/TestModel.swift | 2 +- Tests/Models/Rest/EncryptedModel.swift | 2 +- Tests/Models/Rest/ErrorModel.swift | 2 +- Tests/Models/Rest/FileResponse.swift | 2 +- Tests/Models/Rest/StatusCode.swift | 2 +- Tests/Models/Rest/TestHeaders.swift | 2 +- Tests/Models/Rest/TestJSONParams.swift | 2 +- Tests/Models/Rest/TestParams.swift | 2 +- Tests/StatusCodeTransformer.swift | 2 +- Tests/TestCache.swift | 2 +- Tests/TestConfiguration.swift | 40 +++-- Tests/TestDownloadOperations.swift | 10 +- Tests/TestDownloadOperationsAsync.swift | 14 +- Tests/TestEnvironment.swift | 2 +- Tests/TestExtensions.swift | 2 +- Tests/TestHelpers.swift | 2 +- Tests/TestInterceptors.swift | 32 ++-- Tests/TestMockedRequest.swift | 17 +-- Tests/TestPinning.swift | 6 +- Tests/TestQueue.swift | 2 +- Tests/TestReachability.swift | 2 +- .../{APIRoute.swift => TestRepository.swift} | 140 ++++++++---------- Tests/TestRequest.swift | 64 ++++---- Tests/TestRequestAsync.swift | 33 +---- Tests/TestTNErrors.swift | 53 ++++--- Tests/TestTransformer.swift | 2 +- Tests/TestTransformers.swift | 14 +- Tests/TestUploadOperations.swift | 20 +-- Tests/TestUploadOperationsAsync.swift | 22 +-- Tests/TestUploadTransformer.swift | 2 +- Tests/UnauthorizedInterceptor.swift | 2 +- Tests/www.billp.dev.cer | Bin 1351 -> 1350 bytes 112 files changed, 541 insertions(+), 617 deletions(-) rename Examples/Communication/{Routers/CityRoute.swift => Repositories/CitiesRepository.swift} (50%) rename Examples/Communication/{Routers/MiscRoute.swift => Repositories/MiscRepository.swift} (86%) rename Source/{Router.swift => Client.swift} (79%) rename Source/{RouteConfiguration.swift => EndpointConfiguration.swift} (88%) rename Source/Protocols/{RouteProtocol.swift => EndpointProtocol.swift} (71%) rename Tests/MockData.bundle/{main-router => main-repo}/headers.json (100%) rename Tests/{APIRoute.swift => TestRepository.swift} (50%) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 44552138..dd4c8524 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,9 +9,9 @@ jobs: - name: List available Xcode versions run: ls /Applications | grep Xcode - name: Select Xcode - run: sudo xcode-select -switch /Applications/Xcode_14.1.app && /usr/bin/xcodebuild -version + run: sudo xcode-select -switch /Applications/Xcode_14.2.app && /usr/bin/xcodebuild -version - name: Run unit tests - run: xcodebuild test -scheme TermiNetworkTests -destination 'platform=iOS Simulator,name=iPhone 14 Pro,OS=16.1' + run: xcodebuild test -scheme TermiNetworkTests -destination 'platform=iOS Simulator,name=iPhone 14 Pro,OS=16.2' - name: Upload coverage to Codecov uses: codecov/codecov-action@v1.2.1 diff --git a/Examples/Communication/DemoEnvironment.swift b/Examples/Communication/DemoEnvironment.swift index 98fb1e13..7ebdfc7f 100644 --- a/Examples/Communication/DemoEnvironment.swift +++ b/Examples/Communication/DemoEnvironment.swift @@ -1,6 +1,6 @@ // DemoEnvironment.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Communication/Interceptors/ServiceErrorInterceptor.swift b/Examples/Communication/Interceptors/ServiceErrorInterceptor.swift index b5fca115..491a5acf 100644 --- a/Examples/Communication/Interceptors/ServiceErrorInterceptor.swift +++ b/Examples/Communication/Interceptors/ServiceErrorInterceptor.swift @@ -1,6 +1,6 @@ // GlobalNetworkErrorHandler.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Communication/Middleware/CryptoMiddleware.swift b/Examples/Communication/Middleware/CryptoMiddleware.swift index 6a6086a2..37bdf5fb 100644 --- a/Examples/Communication/Middleware/CryptoMiddleware.swift +++ b/Examples/Communication/Middleware/CryptoMiddleware.swift @@ -1,6 +1,6 @@ // CryptoMiddleware.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Communication/Models/Domain/City.swift b/Examples/Communication/Models/Domain/City.swift index 47b4dd9d..0fd0091a 100644 --- a/Examples/Communication/Models/Domain/City.swift +++ b/Examples/Communication/Models/Domain/City.swift @@ -1,6 +1,6 @@ // City.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Communication/Models/Domain/EncryptedModel.swift b/Examples/Communication/Models/Domain/EncryptedModel.swift index c605417e..d7e9673a 100644 --- a/Examples/Communication/Models/Domain/EncryptedModel.swift +++ b/Examples/Communication/Models/Domain/EncryptedModel.swift @@ -1,6 +1,6 @@ // EncryptedModel.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Communication/Models/Domain/FileResponse.swift b/Examples/Communication/Models/Domain/FileResponse.swift index 74a02e32..507449a7 100644 --- a/Examples/Communication/Models/Domain/FileResponse.swift +++ b/Examples/Communication/Models/Domain/FileResponse.swift @@ -1,6 +1,6 @@ // FileResponse.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Communication/Models/Rest/RSCity.swift b/Examples/Communication/Models/Rest/RSCity.swift index ca97f985..57ecf885 100644 --- a/Examples/Communication/Models/Rest/RSCity.swift +++ b/Examples/Communication/Models/Rest/RSCity.swift @@ -1,6 +1,6 @@ // RSCity.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Communication/Models/Rest/RSEncryptedModel.swift b/Examples/Communication/Models/Rest/RSEncryptedModel.swift index 9d11df1b..a24f8b1a 100644 --- a/Examples/Communication/Models/Rest/RSEncryptedModel.swift +++ b/Examples/Communication/Models/Rest/RSEncryptedModel.swift @@ -1,6 +1,6 @@ // RSEncryptedModel.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Communication/Models/Rest/RSFileResponse.swift b/Examples/Communication/Models/Rest/RSFileResponse.swift index 83984089..31cf83c4 100644 --- a/Examples/Communication/Models/Rest/RSFileResponse.swift +++ b/Examples/Communication/Models/Rest/RSFileResponse.swift @@ -1,6 +1,6 @@ // RSFileResponse.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Communication/Routers/CityRoute.swift b/Examples/Communication/Repositories/CitiesRepository.swift similarity index 50% rename from Examples/Communication/Routers/CityRoute.swift rename to Examples/Communication/Repositories/CitiesRepository.swift index b98dbd5b..31f8fb82 100644 --- a/Examples/Communication/Routers/CityRoute.swift +++ b/Examples/Communication/Repositories/CitiesRepository.swift @@ -1,6 +1,6 @@ -// CityRoute.swift +// CitiesRepository.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -20,40 +20,35 @@ import Foundation import TermiNetwork -enum CityRoute: RouteProtocol { +enum CitiesRepository: EndpointProtocol { case cities case city(id: Int) case thumb(city: City) case image(city: City) case pinning(configuration: Configuration) - func configure() -> RouteConfiguration { + func configure() -> EndpointConfiguration { switch self { case .cities: - return RouteConfiguration(method: .get, - path: .path(["cities"]), - mockFilePath: - .path(["Cities", "cities.json"])) + return .init(method: .get, + path: .path(["cities"]), + mockFilePath: .path(["Cities", "cities.json"])) case .city(let id): - return RouteConfiguration(method: .get, - path: .path(["city", String(id)]), - mockFilePath: - .path(["Cities", "Details", String(format: "%i.json", id)])) + return .init(method: .get, + path: .path(["city", String(id)]), + mockFilePath: .path(["Cities", "Details", String(format: "%i.json", id)])) case .thumb(let city): - return RouteConfiguration(method: .get, - path: .path([city.thumb ?? ""]), - mockFilePath: - .path(["Cities", "Thumbs", String(format: "%i.jpg", city.cityID)])) + return .init(method: .get, + path: .path([city.thumb ?? ""]), + mockFilePath: .path(["Cities", "Thumbs", String(format: "%i.jpg", city.cityID)])) case .image(let city): - return RouteConfiguration(method: .get, - path: .path([city.image ?? ""]), - mockFilePath: - .path(["Cities", "Images", String(format: "%i.jpg", city.cityID)])) + return .init(method: .get, + path: .path([city.image ?? ""]), + mockFilePath: .path(["Cities", "Images", String(format: "%i.jpg", city.cityID)])) case .pinning(let configuration): - return RouteConfiguration( - method: .get, - path: .path(["cities"]), - configuration: configuration + return .init(method: .get, + path: .path(["cities"]), + configuration: configuration ) } } diff --git a/Examples/Communication/Routers/MiscRoute.swift b/Examples/Communication/Repositories/MiscRepository.swift similarity index 86% rename from Examples/Communication/Routers/MiscRoute.swift rename to Examples/Communication/Repositories/MiscRepository.swift index 2d59edad..6a746cc6 100644 --- a/Examples/Communication/Routers/MiscRoute.swift +++ b/Examples/Communication/Repositories/MiscRepository.swift @@ -1,6 +1,6 @@ -// MiscRoute.swift +// MiscRepository.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -20,20 +20,20 @@ import Foundation import TermiNetwork -enum MiscRoute: RouteProtocol { +enum MiscRepository: EndpointProtocol { case testEncryptParams(param: String) case upload(fileUrl: URL) - func configure() -> RouteConfiguration { + func configure() -> EndpointConfiguration { switch self { case .testEncryptParams(let value): - return RouteConfiguration( + return EndpointConfiguration( method: .post, path: .path(["test_encrypt_params"]), params: ["value": value] ) case .upload(fileUrl: let fileUrl): - return RouteConfiguration( + return EndpointConfiguration( method: .post, path: .path(["file_upload"]), params: ["file": MultipartFormDataPartType.url(fileUrl)] diff --git a/Examples/Communication/Transformers/CitiesTransformer.swift b/Examples/Communication/Transformers/CitiesTransformer.swift index abaa21ce..5719c177 100644 --- a/Examples/Communication/Transformers/CitiesTransformer.swift +++ b/Examples/Communication/Transformers/CitiesTransformer.swift @@ -1,6 +1,6 @@ // CitiesTransformer.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Communication/Transformers/CityTransformer.swift b/Examples/Communication/Transformers/CityTransformer.swift index 3e6c8f0c..1056db5a 100644 --- a/Examples/Communication/Transformers/CityTransformer.swift +++ b/Examples/Communication/Transformers/CityTransformer.swift @@ -1,6 +1,6 @@ // CityTransformer.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Communication/Transformers/EncryptedModelTransformer.swift b/Examples/Communication/Transformers/EncryptedModelTransformer.swift index 048e0094..eea47de3 100644 --- a/Examples/Communication/Transformers/EncryptedModelTransformer.swift +++ b/Examples/Communication/Transformers/EncryptedModelTransformer.swift @@ -1,6 +1,6 @@ // EncryptedModelTransformer.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Communication/Transformers/FileUploadTransformer.swift b/Examples/Communication/Transformers/FileUploadTransformer.swift index dbd47a31..a7e38db8 100644 --- a/Examples/Communication/Transformers/FileUploadTransformer.swift +++ b/Examples/Communication/Transformers/FileUploadTransformer.swift @@ -1,6 +1,6 @@ // FileUploadTransformer.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Screens/AppDelegate.swift b/Examples/Screens/AppDelegate.swift index 4bbac0bd..cebe8ade 100644 --- a/Examples/Screens/AppDelegate.swift +++ b/Examples/Screens/AppDelegate.swift @@ -1,6 +1,6 @@ // AppDelegate.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Screens/City Explorer/CityExplorerDetails.swift b/Examples/Screens/City Explorer/CityExplorerDetails.swift index e55ab5a2..7d6b6a23 100644 --- a/Examples/Screens/City Explorer/CityExplorerDetails.swift +++ b/Examples/Screens/City Explorer/CityExplorerDetails.swift @@ -1,6 +1,6 @@ // CityExplorerDetails.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -46,13 +46,12 @@ struct CityExplorerDetails: View { } } .navigationTitle(viewModel.city.name) - .onAppear(perform: viewModel.onAppear) - .onDisappear(perform: viewModel.onDisappear) + .task(viewModel.loadCity) } } extension CityExplorerDetails { - class ViewModel: ObservableObject { + @MainActor class ViewModel: ObservableObject { var fetchCityDetailsTask: Task<(), Never>? @Published var city: City var cityFetched: Bool = false @@ -64,21 +63,8 @@ extension CityExplorerDetails { self.usesMockData = usesMockData } - func onAppear() { - guard fetchCityDetailsTask == nil else { - return - } - fetchCityDetailsTask = Task { - await loadCity() - } - } - - func onDisappear() { - fetchCityDetailsTask?.cancel() - } - - @MainActor func loadCity() async { - let request = Router().request(for: .city(id: city.cityID)) + @Sendable func loadCity() async { + let request = Client().request(for: .city(id: city.cityID)) do { city = try await request.asyncUpload(using: CityTransformer.self) @@ -114,7 +100,7 @@ struct CityDetailsEntry: View { } var thumbView: some View { - TermiNetwork.Image(request: Router().request(for: .image(city: city))) + TermiNetwork.Image(request: Client().request(for: .image(city: city))) .aspectRatio(contentMode: .fill) } } diff --git a/Examples/Screens/City Explorer/CityExplorerView.swift b/Examples/Screens/City Explorer/CityExplorerView.swift index 854ffe45..87d47432 100644 --- a/Examples/Screens/City Explorer/CityExplorerView.swift +++ b/Examples/Screens/City Explorer/CityExplorerView.swift @@ -1,6 +1,6 @@ // CityExplorerView.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -45,12 +45,7 @@ struct CityExplorerView: View { } } .navigationTitle("City Explorer") - .onAppear { [unowned viewModel] in - viewModel.onAppear() - } - .onDisappear { [unowned viewModel] in - viewModel.onDissapear() - } + .task(viewModel.loadCities) } } @@ -74,7 +69,7 @@ struct CityRow: View { @ViewBuilder var thumbView: some View { - let request = Router().request(for: .thumb(city: city)) + let request = Client().request(for: .thumb(city: city)) ZStack { if !imageLoaded { @@ -94,7 +89,7 @@ struct CityRow: View { extension CityExplorerView { @MainActor class ViewModel: ObservableObject { - private var fetchCitiesTask: Task<(), Never>? + private var initialRequestCompleted: Bool = false @Published var cities: [City] = [] @Published var errorMessage: String? @@ -106,24 +101,15 @@ extension CityExplorerView { Environment.current.configuration?.mockDataEnabled = usesMockData } - func onAppear() { - guard fetchCitiesTask == nil else { + @Sendable func loadCities() async { + guard !initialRequestCompleted else { return } - self.fetchCitiesTask = Task { - await loadCities() - } - } - - func onDissapear() { - fetchCitiesTask?.cancel() - } - - func loadCities() async { do { - cities = try await Router() + cities = try await Client() .request(for: .cities) .async(using: CitiesTransformer.self) + initialRequestCompleted = true } catch let error { if let error = error as? TNError { self.errorMessage = error.localizedDescription diff --git a/Examples/Screens/ContentView.swift b/Examples/Screens/ContentView.swift index 7ef4a4c6..7e10313d 100644 --- a/Examples/Screens/ContentView.swift +++ b/Examples/Screens/ContentView.swift @@ -1,6 +1,6 @@ // ContentView.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Screens/DemoApp.swift b/Examples/Screens/DemoApp.swift index 66c44d56..64e383fe 100644 --- a/Examples/Screens/DemoApp.swift +++ b/Examples/Screens/DemoApp.swift @@ -1,6 +1,6 @@ // DemoApp.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -31,12 +31,12 @@ struct DemoApp: Identifiable { [ DemoApp( name: "City Explorer", - description: "Router, Transformers, Codables", + description: "Repository, Transformers, Codables", destination: AnyView(CityExplorerView(viewModel: .init(usesMockData: false))) ), DemoApp( name: "City Explorer - Offline Mode", - description: "Router, Transformers, Codables, Mock Data", + description: "Repository, Transformers, Codables, Mock Data", destination: AnyView(CityExplorerView(viewModel: .init(usesMockData: true))) ), DemoApp( diff --git a/Examples/Screens/Encrypted Communication/EncryptedCommunicationView.swift b/Examples/Screens/Encrypted Communication/EncryptedCommunicationView.swift index 2c1bb890..4ec17774 100644 --- a/Examples/Screens/Encrypted Communication/EncryptedCommunicationView.swift +++ b/Examples/Screens/Encrypted Communication/EncryptedCommunicationView.swift @@ -1,6 +1,6 @@ // EncryptedCommunicationView.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -67,7 +67,7 @@ struct EncryptedCommunicationView: View { func startRequest() { responseString = "fetching..." - Router(configuration: configuration) + Client(configuration: configuration) .request(for: .testEncryptParams(param: text)) .success(transformer: EncryptedModelTransformer.self) { model in responseString = model.text diff --git a/Examples/Screens/File Downloader/FileDownloader.swift b/Examples/Screens/File Downloader/FileDownloader.swift index ee1edf9a..81e40245 100644 --- a/Examples/Screens/File Downloader/FileDownloader.swift +++ b/Examples/Screens/File Downloader/FileDownloader.swift @@ -1,6 +1,6 @@ // FileDownloader.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Screens/File Uploader/FileUploader.swift b/Examples/Screens/File Uploader/FileUploader.swift index 29a4a2b7..d7cdb8a2 100644 --- a/Examples/Screens/File Uploader/FileUploader.swift +++ b/Examples/Screens/File Uploader/FileUploader.swift @@ -1,6 +1,6 @@ // FileUploader.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -172,7 +172,7 @@ extension FileUploader { uploadStarted = true uploadFinished = false - let response = try await Router() + let response = try await Client() .request(for: .upload(fileUrl: imageUrl)) .asyncUpload( using: FileUploadTransformer.self, diff --git a/Examples/Screens/File Uploader/FileUploaderUtils.swift b/Examples/Screens/File Uploader/FileUploaderUtils.swift index 8f07a14b..0de66b9a 100644 --- a/Examples/Screens/File Uploader/FileUploaderUtils.swift +++ b/Examples/Screens/File Uploader/FileUploaderUtils.swift @@ -1,6 +1,6 @@ // FileUploaderUtils.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Screens/Pinning/CertificatePinningView.swift b/Examples/Screens/Pinning/CertificatePinningView.swift index 1b7c0f77..3c51b6f9 100644 --- a/Examples/Screens/Pinning/CertificatePinningView.swift +++ b/Examples/Screens/Pinning/CertificatePinningView.swift @@ -1,6 +1,6 @@ // CertificatePinningView.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -61,7 +61,7 @@ struct CertificatePinningView: View { responseString = "fetching..." - Router() + Client() .request(for: .pinning(configuration: configuration)) .success(responseType: Data.self) { response in responseString = response.toJSONString() ?? "" diff --git a/Examples/Screens/Reachability/Reachability.swift b/Examples/Screens/Reachability/Reachability.swift index a94c9348..7be79be0 100644 --- a/Examples/Screens/Reachability/Reachability.swift +++ b/Examples/Screens/Reachability/Reachability.swift @@ -1,6 +1,6 @@ // Reachability.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Screens/TermiNetworkExamplesApp.swift b/Examples/Screens/TermiNetworkExamplesApp.swift index cfdb440a..53c08ca5 100644 --- a/Examples/Screens/TermiNetworkExamplesApp.swift +++ b/Examples/Screens/TermiNetworkExamplesApp.swift @@ -1,6 +1,6 @@ // TermiNetworkExamplesApp.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Examples/Screens/UIHelpers.swift b/Examples/Screens/UIHelpers.swift index dce15ff7..ee2b5e3f 100644 --- a/Examples/Screens/UIHelpers.swift +++ b/Examples/Screens/UIHelpers.swift @@ -1,6 +1,6 @@ // UIHelpers.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Package.swift b/Package.swift index 466cd636..a187e987 100644 --- a/Package.swift +++ b/Package.swift @@ -1,12 +1,12 @@ -// swift-tools-version:5.1 +// swift-tools-version:5.7 import PackageDescription let package = Package( name: "TermiNetwork", platforms: [ .macOS(.v10_15), - .iOS(.v13), - .tvOS(.v13), + .iOS(.v14), + .tvOS(.v14), .watchOS(.v6) ], products: [ diff --git a/README.md b/README.md index 7e9a84b5..4a15811f 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ - [x] Async await support
- [x] Decodes response to the given type: Codable, Transformer, UIImage, Data or String
- [x] UIKit/SwiftUI extensions for downloading remote images
-- [x] Request grouping with Routers
+- [x] Request grouping with Repositories
- [x] Detects network status with Reachability
- [x] Transformers: convert models from one type to another easily
- [x] Error Handling
@@ -51,9 +51,9 @@ - [Usage](#usage) - [Simple usage of Request](#simple_usage) - [Advanced usage of Request with Configuration and custom Queue](#advanced_usage) - - [Complete project setup with Environments and Routers (Recommended)](#complete_setup) + - [Complete project setup with Environments and Repositories (Recommended)](#complete_setup) - [Environment setup](#setup_environments) - - [Router setup](#setup_routers) + - [Repository setup](#setup_repositories) - [Make a request](#construct_request) - [Queue Hooks](#queue_hooks) - [Error Handling](#error_handling) @@ -225,8 +225,8 @@ The request above uses a custom queue **myQueue** with a failure mode of **.cont -## Complete setup with Environments and Routers -The complete and recommended setup of TermiNetwork consists of defining **Environments** and **Routers**. +## Complete setup with Environments and Repositories +The complete and recommended setup of TermiNetwork consists of defining **Environments** and **Repositories**. @@ -254,71 +254,73 @@ enum MyAppEnvironments: EnvironmentProtocol { } } ``` -*Optionally you can pass a **configuration** object to make all Routers and Requests to inherit the given configuration settings.* +*Optionally you can pass a **configuration** object to make all Repositories and Endpoints to inherit the given configuration settings.* To set your global environment use Environment.set method ```swift Environment.set(MyAppEnvironments.development) ``` - + -#### Router setup -Create a swift **enum** that implements the **RouteProtocol** and define your environments. +#### Repository setup +Create a swift **enum** that implements the **EndpointProtocol** and define your endpoints. -The following example creates a TodosRoute with all the required API routes (cases). +The following example creates a TodosRepository with all the required endpoints as cases. ##### Example ```swift -enum TodosRoute: RouteProtocol { - // Define your routes +enum TodosRepository: EndpointProtocol { + // Define your endpoints case list case show(id: Int) case add(title: String) case remove(id: Int) case setCompleted(id: Int, completed: Bool) - // Set method, path, params, headers for each route - func configure() -> RouteConfiguration { - let configuration = Configuration(requestBodyType: .JSON, - headers: ["x-auth": "abcdef1234"]) + static let configuration = Configuration(requestBodyType: .JSON, + headers: ["x-auth": "abcdef1234"]) + + + // Set method, path, params, headers for each endpoint + func configure() -> EndpointConfiguration { switch self { case .list: - return RouteConfiguration(method: .get, - path: .path(["todos"]), // GET /todos - configuration: configuration) + return .init(method: .get, + path: .path(["todos"]), // GET /todos + configuration: Self.configuration) case .show(let id): - return RouteConfiguration(method: .get, - path: .path(["todo", String(id)]), // GET /todos/[id] - configuration: configuration) + return .init(method: .get, + path: .path(["todo", String(id)]), // GET /todos/[id] + configuration: Self.configuration) case .add(let title): - return RouteConfiguration(method: .post, - path: .path(["todos"]), // POST /todos - params: ["title": title], - configuration: configuration) + return .init(method: .post, + path: .path(["todos"]), // POST /todos + params: ["title": title], + configuration: Self.configuration) case .remove(let id): - return RouteConfiguration(method: .delete, - path: .path(["todo", String(id)]), // DELETE /todo/[id] - configuration: configuration) + return .init(method: .delete, + path: .path(["todo", String(id)]), // DELETE /todo/[id] + configuration: configuration) case .setCompleted(let id, let completed): - return RouteConfiguration(method: .patch, - path: .path(["todo", String(id)]), // PATCH /todo/[id] - params: ["completed": completed], - configuration: configuration) + return .init(method: .patch, + path: .path(["todo", String(id)]), // PATCH /todo/[id] + params: ["completed": completed], + configuration: configuration) } } } ``` -You can optionally pass a **configuration** object to each case if you want provide different configuration for each route. +You can optionally pass a **configuration** object to each case if you want provide different configuration for each endpoint. #### Make a request -To create the request you have to initialize a **Router** instance and specialize it with your defined Router, in our case **TodosRoute**: +To create the request you have to initialize a **Client** instance and specialize it with your defined Repository, in our case **TodosRepository**: ```swift -Router().request(for: .add(title: "Go shopping!")) +Client().request(for: .add(title: "Go shopping!")) .success(responseType: Todo.self) { todo in // do something with todo } @@ -331,7 +333,7 @@ or with **async await** ```swift do { - let toto: Todo = Router() + let toto: Todo = Client() .request(for: .add(title: "Go shopping!")) .async() } catch let error { @@ -376,7 +378,7 @@ To see all the available errors, please visit the ().request(for: .add(title: "Go shopping!")) .success(responseType: Todo.self) { todo in // do something with todo } @@ -399,13 +401,14 @@ Router().request(for: .add(title: "Go shopping!")) or with **async await** ```swift do { - let todo: Todo = Router() + let todo: Todo = Client() .request(for: .add(title: "Go shopping!")) .async() } catch let error { switch error as? TNError { - case .notSuccess(let statusCode, _): - debugPrint("Status code " + String(statusCode)) + case .notSuccess(let statusCode, let data): + let errorModel = try? data.deserializeJSONData() as MyErrorModel + debugPrint("Status code " + String(statusCode) + ". API Error: " + errorModel?.errorMessage) break case .networkError(let error): debugPrint("Network error: " + error.localizedDescription) @@ -509,7 +512,7 @@ final class CitiesTransformer: Transformer<[RSCity], [City]> { Finally, pass the **CitiesTransformer** in the Request's start method: #### Example ```swift -Router() +Client() .request(for: .cities) .success(transformer: CitiesTransformer.self) { cities in self.cities = cities @@ -527,7 +530,7 @@ Router() or with **async await** ```swift do { - let cities = await Router() + let cities = await Client() .request(for: .cities) .async(using: CitiesTransformer.self) } catch let error { @@ -560,18 +563,18 @@ do { ```swift configuration.mockDataEnabled = true ``` -4. Define the mockFilePath path in your Routes +4. Define the mockFilePath path in your endpoints. #### Example ```swift - enum CityRoute: RouteProtocol { - case cities + enum CitiesRepository: EndpointProtocol { + case cities - func configure() -> RouteConfiguration { + func configure() -> EndpointConfiguration { switch self { case .cities: - return RouteConfiguration(method: .get, - path: .path(["cities"]), - mockFilePath: .path(["Cities", "cities.json"])) + return EndpointConfiguration(method: .get, + path: .path(["cities"]), + mockFilePath: .path(["Cities", "cities.json"])) } } } @@ -655,7 +658,7 @@ TermiNetwork provides two different helpers for setting remote images. ```swift var body: some View { - TermiNetwork.Image(withRequest: Router().request(for: .image(city: city)), + TermiNetwork.Image(withRequest: Client().request(for: .image(city: city)), defaultImage: UIImage(named: "DefaultThumbImage")) } ``` @@ -680,7 +683,7 @@ TermiNetwork provides two different helpers for setting remote images. ```swift let imageView = UIImageView() // or NSImageView (macOS), or WKInterfaceImage (watchOS) - imageView.tn_setRemoteImage(request: Router().request(for: .thumb(withID: "3125")), + imageView.tn_setRemoteImage(request: Client().request(for: .thumb(withID: "3125")), defaultImage: UIImage(named: "DefaultThumbImage"), preprocessImage: { image in // Optionally pre-process image and return the new image. diff --git a/Source/Cache.swift b/Source/Cache.swift index 555d01c4..f4508709 100644 --- a/Source/Cache.swift +++ b/Source/Cache.swift @@ -1,6 +1,6 @@ // Cache.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/CertificatePinningManager.swift b/Source/CertificatePinningManager.swift index 38df2fb2..00586369 100644 --- a/Source/CertificatePinningManager.swift +++ b/Source/CertificatePinningManager.swift @@ -1,6 +1,6 @@ // CertificatePinningManager.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Router.swift b/Source/Client.swift similarity index 79% rename from Source/Router.swift rename to Source/Client.swift index 702556d8..23cfb93e 100644 --- a/Source/Router.swift +++ b/Source/Client.swift @@ -1,6 +1,6 @@ -// Router.swift +// Client.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -19,12 +19,12 @@ import Foundation -/// This class is used to create instances of Router that can be used to start requests based on the given Route. -public final class Router { +/// This class is used to create instances of Repository that can be used to start requests based on the given endpoint. +public final class Client { // MARK: Properties fileprivate var environment: Environment? - /// Router configuration + /// Repository configuration public var configuration: Configuration? /// Initialize with environment that overrides the one set by Environment.set(_). @@ -37,9 +37,9 @@ public final class Router { /// Returns a Request that can be used later, e.g. for starting the request in a later time or canceling it. /// /// - parameters: - /// - route: a RouteProtocol enum value - public func request(for route: Route) -> Request { - Request(route: route, + /// - endpoint: a RepositoryProtocol enum value. + public func request(for endpoint: Repository) -> Request { + Request(endpoint: endpoint, environment: environment, configuration: configuration) } diff --git a/Source/Configuration.swift b/Source/Configuration.swift index 36587482..1c8759e7 100644 --- a/Source/Configuration.swift +++ b/Source/Configuration.swift @@ -1,6 +1,6 @@ // Configuration.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -25,11 +25,12 @@ import Foundation /// - max: The upper bound of interval. public typealias MockDelayRange = (min: TimeInterval, max: TimeInterval) -/// A configuration class that can be used with Environment, Router, Route and Request. +/// A configuration class that can be used with Environment, Repository, Endpoint and Request. /// A configuration object follows the following rules: /// 1. When a Configuration object is passed to an Environment, -/// each Router with its routes and requests will inherit this configuration. -/// 2. When a Configuration object is passed to Router, all its routes and requests will inherit this configuration. +/// each Repository with its Endpoints and requests will inherit this configuration. +/// 2. When a Configuration object is passed to Repository, +/// all its Endpoints and Requests will inherit this configuration. public final class Configuration { // MARK: Public properties @@ -49,7 +50,7 @@ public final class Configuration { } /// Enables or disables debug mode. public var verbose: Bool? - /// Additional headers of the request. They will be merged with the headers specified in RouteConfiguration. + /// Additional headers of the request. They will be merged with the headers specified in EndpointConfiguration. public var headers: [String: String]? /// The Bundle object of mock data used when useMockData is true. public var mockDataBundle: Bundle? @@ -82,7 +83,7 @@ public final class Configuration { /// - certificatePaths: The certificate file paths used for certificate pining. /// - verbose: Enables or disables debug mode. /// - headers: Additional headers of the request. Will be merged with the headers specified - /// in RouteConfiguration. + /// in EndpointConfiguration. /// - mockDataBundle: The Bundle object of mock data used when useMockData is true. /// - mockDataEnabled: Enables or disables request mocking. /// - mockDelay: Specifies a delay when mock data is used. diff --git a/Source/RouteConfiguration.swift b/Source/EndpointConfiguration.swift similarity index 88% rename from Source/RouteConfiguration.swift rename to Source/EndpointConfiguration.swift index c1439520..f06d45ad 100644 --- a/Source/RouteConfiguration.swift +++ b/Source/EndpointConfiguration.swift @@ -1,6 +1,6 @@ -// RouteConfiguration.swift +// EndpointConfiguration.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -19,8 +19,8 @@ import Foundation -/// Route configuration class which is used in Route protocol implementations. -public final class RouteConfiguration { +/// Endpoint configuration class which is used in EndpointProtocol implementations. +public final class EndpointConfiguration { /// A Method to use, for example .get, .post, etc. var method: Method /// A path of the request (will be appended to the base URL, for example .path(["user", "13"]). @@ -29,20 +29,20 @@ public final class RouteConfiguration { var params: [String: Any?]? /// The headers of the request. They will override (if needed) those from configuration objects. var headers: [String: String]? - /// A configuration object (Optional, e.g. if you want ot use custom configuration for a specific route). + /// A configuration object (Optional, e.g. if you want ot use custom configuration for a specific endpoint). var configuration: Configuration? /// A path of the file in the mock data bundle specified in configuration object. /// This will be used only if useMockData is set to true in the configuration object. var mockFilePath: Path? - /// Route configuration initializer + /// Endpoint configuration initializer. /// /// - parameters: /// - method: A Method to use, for example .get, .post, etc. /// - path: A path of the request (will be appended to the base URL, for example .path(["user", "13"]). /// - params: The parameters of the request. /// - headers: A configuration object (Optional, e.g. if you want ot use custom - /// configuration for a specific route). + /// configuration for a specific endpoint). /// - configuration: The configuration object of the request. /// - mockFilePath: A path of the file in the mock data bundle specified in configuration object. /// This will be used only if useMockData is set to true in the configuration object. diff --git a/Source/Environment.swift b/Source/Environment.swift index bfee6639..7316f4cb 100644 --- a/Source/Environment.swift +++ b/Source/Environment.swift @@ -1,6 +1,6 @@ // Environment.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -75,7 +75,7 @@ open class Environment { /// - host: The host name, e.g. s1.example.com /// - suffix: The path after the host name, e.g. .path["api","v1"] /// - port: The port the environment is using, e.g. 8080 - /// - configuration: A configuration instance that will be inherited by each request and route + /// - configuration: A configuration instance that will be inherited by each request and repository. public init(scheme: URLScheme, host: String, suffix: Path? = nil, diff --git a/Source/Extensions/Data+Extensions.swift b/Source/Extensions/Data+Extensions.swift index 84f18ce0..8ba7a163 100644 --- a/Source/Extensions/Data+Extensions.swift +++ b/Source/Extensions/Data+Extensions.swift @@ -1,6 +1,6 @@ // Data+Extensions.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/Dictionary+Extensions.swift b/Source/Extensions/Dictionary+Extensions.swift index 418122bf..c6d7aa9d 100644 --- a/Source/Extensions/Dictionary+Extensions.swift +++ b/Source/Extensions/Dictionary+Extensions.swift @@ -1,6 +1,6 @@ // Dictionary+Extensions.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/Operations/Decodable+Transformer.swift b/Source/Extensions/Operations/Decodable+Transformer.swift index 78abb82c..54777a20 100644 --- a/Source/Extensions/Operations/Decodable+Transformer.swift +++ b/Source/Extensions/Operations/Decodable+Transformer.swift @@ -1,6 +1,6 @@ // Decodable+Transformer.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/Operations/Request+DataOperations.swift b/Source/Extensions/Operations/Request+DataOperations.swift index 318537f8..88b01226 100644 --- a/Source/Extensions/Operations/Request+DataOperations.swift +++ b/Source/Extensions/Operations/Request+DataOperations.swift @@ -1,6 +1,6 @@ // Request+DataOperations.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/Operations/Request+FileOperations.swift b/Source/Extensions/Operations/Request+FileOperations.swift index e38cc06a..196b2507 100644 --- a/Source/Extensions/Operations/Request+FileOperations.swift +++ b/Source/Extensions/Operations/Request+FileOperations.swift @@ -1,6 +1,6 @@ // Request+FileOperations.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/Operations/Request+FileOperationsAsync.swift b/Source/Extensions/Operations/Request+FileOperationsAsync.swift index 1b56b52b..5f0499af 100644 --- a/Source/Extensions/Operations/Request+FileOperationsAsync.swift +++ b/Source/Extensions/Operations/Request+FileOperationsAsync.swift @@ -1,6 +1,6 @@ // Request+FileOperationsAsync.swift // -// Copyright © 2018-2022 Vasilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vasilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/Request+Async.swift b/Source/Extensions/Request+Async.swift index 007bf0ed..4c1c0820 100644 --- a/Source/Extensions/Request+Async.swift +++ b/Source/Extensions/Request+Async.swift @@ -1,6 +1,6 @@ // Request+ResponseTypes.swift // -// Copyright © 2018-2022 Vasilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vasilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/Request+Interceptors.swift b/Source/Extensions/Request+Interceptors.swift index 74fe283a..66aaaea6 100644 --- a/Source/Extensions/Request+Interceptors.swift +++ b/Source/Extensions/Request+Interceptors.swift @@ -1,6 +1,6 @@ // Request+Interceptors.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/Request+Middleware.swift b/Source/Extensions/Request+Middleware.swift index 71868274..c9cae5ca 100644 --- a/Source/Extensions/Request+Middleware.swift +++ b/Source/Extensions/Request+Middleware.swift @@ -1,6 +1,6 @@ // Request+Middleware.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/Request+Mock.swift b/Source/Extensions/Request+Mock.swift index a5855d1c..7152de75 100644 --- a/Source/Extensions/Request+Mock.swift +++ b/Source/Extensions/Request+Mock.swift @@ -1,6 +1,6 @@ // Request+Mock.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/Request+NSCopying.swift b/Source/Extensions/Request+NSCopying.swift index ec4fd99e..62794ffa 100644 --- a/Source/Extensions/Request+NSCopying.swift +++ b/Source/Extensions/Request+NSCopying.swift @@ -1,6 +1,6 @@ // Request+NSCopying.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/Request+ResponseHeaders.swift b/Source/Extensions/Request+ResponseHeaders.swift index b6220622..335ed666 100644 --- a/Source/Extensions/Request+ResponseHeaders.swift +++ b/Source/Extensions/Request+ResponseHeaders.swift @@ -1,6 +1,6 @@ // Request+ResponseHeaders.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/Request+ResponseTypes.swift b/Source/Extensions/Request+ResponseTypes.swift index 92ff04c4..e8393b28 100644 --- a/Source/Extensions/Request+ResponseTypes.swift +++ b/Source/Extensions/Request+ResponseTypes.swift @@ -1,6 +1,6 @@ // Request+ResponseTypes.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/UIImage+Extensions.swift b/Source/Extensions/UIImage+Extensions.swift index 055af68b..6880827b 100644 --- a/Source/Extensions/UIImage+Extensions.swift +++ b/Source/Extensions/UIImage+Extensions.swift @@ -1,6 +1,6 @@ // UIImage+Extensions.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/UIImageView+Extensions.swift b/Source/Extensions/UIImageView+Extensions.swift index a8fd950f..23d40e60 100644 --- a/Source/Extensions/UIImageView+Extensions.swift +++ b/Source/Extensions/UIImageView+Extensions.swift @@ -1,6 +1,6 @@ // UIImageView+Extensions.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Extensions/URLRequest+Extensions.swift b/Source/Extensions/URLRequest+Extensions.swift index c40f0eec..02eaa637 100644 --- a/Source/Extensions/URLRequest+Extensions.swift +++ b/Source/Extensions/URLRequest+Extensions.swift @@ -1,6 +1,6 @@ // Request+Extensions.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/FileStreamer.swift b/Source/FileStreamer.swift index b8b736e9..f1b2cf67 100644 --- a/Source/FileStreamer.swift +++ b/Source/FileStreamer.swift @@ -1,6 +1,6 @@ // FileStreamer.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Helpers/MultipartFormDataHelpers.swift b/Source/Helpers/MultipartFormDataHelpers.swift index 42f7cd5b..d598b30f 100644 --- a/Source/Helpers/MultipartFormDataHelpers.swift +++ b/Source/Helpers/MultipartFormDataHelpers.swift @@ -1,6 +1,6 @@ // MultipartFormDataHelpers.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Helpers/RequestBodyGenerators.swift b/Source/Helpers/RequestBodyGenerators.swift index 92eea8df..48cb8560 100644 --- a/Source/Helpers/RequestBodyGenerators.swift +++ b/Source/Helpers/RequestBodyGenerators.swift @@ -1,6 +1,6 @@ // RequestBodyGenerators.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Helpers/RequestHelpers.swift b/Source/Helpers/RequestHelpers.swift index d4a8edb1..bdfaf6ac 100644 --- a/Source/Helpers/RequestHelpers.swift +++ b/Source/Helpers/RequestHelpers.swift @@ -1,6 +1,6 @@ // RequestHelpers.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Log.swift b/Source/Log.swift index c5b1efb1..726471c9 100644 --- a/Source/Log.swift +++ b/Source/Log.swift @@ -1,6 +1,6 @@ // Log.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -42,82 +42,81 @@ internal class Log { } return } - DispatchQueue.main.async { - let url = urlRequest.url?.absoluteString ?? "n/a" - let headers = urlRequest.allHTTPHeaderFields - print(String(format: "🌎 URL: %@", url)) + let url = urlRequest.url?.absoluteString ?? "n/a" + let headers = urlRequest.allHTTPHeaderFields - if let customError = error { - print(String(format: "❌ Error: %@", (customError.localizedDescription ?? ""))) - } else if let response = request.urlResponse as? HTTPURLResponse { - print(String(format: "✅ Status: %@", String(response.statusCode))) - } + print(String(format: "🌎 URL: %@", url)) - if request.configuration.mockDataEnabled == true { - print("🗂 Mocked response.") - } - print(String(format: "🎛️ Method: %@", request.method.rawValue.uppercased())) - if case .data = request.requestType, - case .started = state { - print(String(format: "🔮 CURL: %@", urlRequest.curlString)) - } + if let customError = error { + print(String(format: "❌ Error: %@", (customError.localizedDescription ?? ""))) + } else if let response = request.urlResponse as? HTTPURLResponse { + print(String(format: "✅ Status: %@", String(response.statusCode))) + } - if request.configuration.certificateData != nil { - print("🔒 Pinning Enabled") - } + if request.configuration.mockDataEnabled == true { + print("🗂 Mocked response.") + } + print(String(format: "🎛️ Method: %@", request.method.rawValue.uppercased())) + if case .data = request.requestType, + case .started = state { + print(String(format: "🔮 CURL: %@", urlRequest.curlString)) + } - if let middleware = request.configuration.requestMiddleware, middleware.count > 0 { - print(String(format: "🧪 Middleware: %@", - middleware.map { String(describing: $0) } - .joined(separator: ", "))) - } + if request.configuration.certificateData != nil { + print("🔒 Pinning Enabled") + } - if let params = request.params as [String: AnyObject]?, - params.keys.count > 0, - request.method != .get { - if case .upload = request.requestType { - print("🗃️ Request Body: multipart/form-data") - } else { - print(String(format: "🗃️ Request Body: %@", (params.toJSONString() ?? ""))) - } - } + if let middleware = request.configuration.requestMiddleware, middleware.count > 0 { + print(String(format: "🧪 Middleware: %@", + middleware.map { String(describing: $0) } + .joined(separator: ", "))) + } - switch state { - case .started: - if let headers = headers, headers.keys.count > 0 { - print(String(format: "📃 Request Headers: %@", headers.toJSONString() ?? "")) - } - case .finished: - request.responseHeaders { (headers, _) in - print(String(format: "📃 Response Headers: %@", headers?.toJSONString() ?? "")) - } - default: - break + if let params = request.params as [String: AnyObject]?, + params.keys.count > 0, + request.method != .get { + if case .upload = request.requestType { + print("🗃️ Request Body: multipart/form-data") + } else { + print(String(format: "🗃️ Request Body: %@", (params.toJSONString() ?? ""))) } + } - if let data = data, !data.isEmpty { - if let responseJSON = data.toJSONString() { - print(String(format: "📦 Response: %@", responseJSON)) - } else if let stringResponse = String(data: data, encoding: .utf8) { - print(String(format: "📦 Response: %@", - (stringResponse.isEmpty ? "[empty-response]" : stringResponse))) - } else { - print("📦 Response: [non-printable]") - } - } else if case .download(let destinationPath) = request.requestType, - case .finished = state, error == nil { - print(String(format: "📦 File saved to: '%@'", destinationPath)) + switch state { + case .started: + if let headers = headers, headers.keys.count > 0 { + print(String(format: "📃 Request Headers: %@", headers.toJSONString() ?? "")) } + case .finished: + request.responseHeaders { (headers, _) in + print(String(format: "📃 Response Headers: %@", headers?.toJSONString() ?? "")) + } + default: + break + } - switch state { - case .started: - print("🚀 Request Started...\n") - case .finished: - print(String(format: "🏁 Request completed in %.5f seconds.\n", request.duration ?? 0)) - case .unknown: - break + if let data = data, !data.isEmpty { + if let responseJSON = data.toJSONString() { + print(String(format: "📦 Response: %@", responseJSON)) + } else if let stringResponse = String(data: data, encoding: .utf8) { + print(String(format: "📦 Response: %@", + (stringResponse.isEmpty ? "[empty-response]" : stringResponse))) + } else { + print("📦 Response: [non-printable]") } + } else if case .download(let destinationPath) = request.requestType, + case .finished = state, error == nil { + print(String(format: "📦 File saved to: '%@'", destinationPath)) + } + + switch state { + case .started: + print("🚀 Request Started...\n") + case .finished: + print(String(format: "🏁 Request completed in %.5f seconds.\n", request.duration ?? 0)) + case .unknown: + break } } diff --git a/Source/MultipartFormDataPartType.swift b/Source/MultipartFormDataPartType.swift index bb598cce..53b2445d 100644 --- a/Source/MultipartFormDataPartType.swift +++ b/Source/MultipartFormDataPartType.swift @@ -1,6 +1,6 @@ // MultipartFormDataPartType.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/MultipartFormDataStream.swift b/Source/MultipartFormDataStream.swift index 3120e75d..c87c3e03 100644 --- a/Source/MultipartFormDataStream.swift +++ b/Source/MultipartFormDataStream.swift @@ -1,6 +1,6 @@ // MultipartFormDataStream.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Operation.swift b/Source/Operation.swift index 2ab2d063..9ec8b875 100644 --- a/Source/Operation.swift +++ b/Source/Operation.swift @@ -1,6 +1,6 @@ // Operation.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Path.swift b/Source/Path.swift index 90e0d811..0af9f1f4 100644 --- a/Source/Path.swift +++ b/Source/Path.swift @@ -1,6 +1,6 @@ // Path.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Protocols/RouteProtocol.swift b/Source/Protocols/EndpointProtocol.swift similarity index 71% rename from Source/Protocols/RouteProtocol.swift rename to Source/Protocols/EndpointProtocol.swift index 4e5a69f2..41d0d5b8 100644 --- a/Source/Protocols/RouteProtocol.swift +++ b/Source/Protocols/EndpointProtocol.swift @@ -1,6 +1,6 @@ -// RouteProtocol.swift +// EndpointProtocol.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -19,9 +19,10 @@ import Foundation -/// Use this protocol to define routers as enums. -public protocol RouteProtocol { - /// Configure your router by setting this function. See Examples/Routers/CityRoute.swift for an example. - /// - returns: A RouteConfiguration object for each route. - func configure() -> RouteConfiguration +/// Use this protocol to define repositories as enums. +public protocol EndpointProtocol { + /// Configure your endpoints by setting defining this function. See + /// Examples/Communication/Repositories/CitiesRepository.swift for an example. + /// - returns: An EndpointProtocol for each endpoint. + func configure() -> EndpointConfiguration } diff --git a/Source/Protocols/InterceptorProtocol.swift b/Source/Protocols/InterceptorProtocol.swift index 5c3dbc98..b1d5ab32 100644 --- a/Source/Protocols/InterceptorProtocol.swift +++ b/Source/Protocols/InterceptorProtocol.swift @@ -1,6 +1,6 @@ // InterceptorProtocol.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Protocols/RequestMiddlewareProtocol.swift b/Source/Protocols/RequestMiddlewareProtocol.swift index 264a3d14..81a53775 100644 --- a/Source/Protocols/RequestMiddlewareProtocol.swift +++ b/Source/Protocols/RequestMiddlewareProtocol.swift @@ -1,6 +1,6 @@ // RequestMiddlewareProtocol.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Queue.swift b/Source/Queue.swift index df5cd78e..4eb3e802 100644 --- a/Source/Queue.swift +++ b/Source/Queue.swift @@ -1,6 +1,6 @@ // Queue.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Reachability.swift b/Source/Reachability.swift index 6db7d357..0638e704 100644 --- a/Source/Reachability.swift +++ b/Source/Reachability.swift @@ -1,6 +1,6 @@ // Reachability.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/Request.swift b/Source/Request.swift index 40db59b2..866b9b81 100644 --- a/Source/Request.swift +++ b/Source/Request.swift @@ -1,6 +1,6 @@ // Request.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -160,40 +160,40 @@ public final class Request: Operation { /// Initializes a Request. /// /// - parameters: - /// - route: a RouteProtocol enum value - internal init(route: RouteProtocol, + /// - endpoint: a EndpointProtocol enum value + internal init(endpoint: EndpointProtocol, environment: Environment? = Environment.current, configuration: Configuration? = nil) { - let route = route.configure() - self.method = route.method - self.headers = route.headers - self.params = route.params - self.path = route.path.convertedPath + let repositoryConfiguration = endpoint.configure() + self.method = repositoryConfiguration.method + self.headers = repositoryConfiguration.headers + self.params = repositoryConfiguration.params + self.path = repositoryConfiguration.path.convertedPath self.environment = environment - self.mockFilePath = route.mockFilePath + self.mockFilePath = repositoryConfiguration.mockFilePath if let environmentConfiguration = environment?.configuration { self.configuration = Configuration.override(left: self.configuration, right: environmentConfiguration) } - if let routerConfiguration = configuration { + if let configuration { self.configuration = Configuration.override(left: self.configuration, - right: routerConfiguration) + right: configuration) } - if let routeConfiguration = route.configuration { + if let repositoryConfiguration = repositoryConfiguration.configuration { self.configuration = Configuration.override(left: self.configuration, - right: routeConfiguration) + right: repositoryConfiguration) } } /// Initializes a Request. /// /// - parameters: - /// - route: a RouteProtocol enum value + /// - endpoint: a EndpointProtocol enum value. /// - environment: Specifies a different environment to use than the global setted environment. - public convenience init(route: RouteProtocol, + public convenience init(endpoint: EndpointProtocol, environment: Environment? = Environment.current) { - self.init(route: route, + self.init(endpoint: endpoint, environment: environment, configuration: nil) } @@ -206,7 +206,7 @@ public final class Request: Operation { let urlString = NSMutableString() if pathType == .relative { - guard let currentEnvironment = environment else { throw TNError.environmenotSet } + guard let currentEnvironment = environment else { throw TNError.environmentNotSet } urlString.setString(currentEnvironment.stringURL + "/" + path) } else { urlString.setString(path) @@ -296,13 +296,11 @@ public final class Request: Operation { } fileprivate func setHeaders() throws { - /// Merge headers with the following order environment > route > request + /// Merges headers in the following order: environment > endpoint > request if headers == nil { headers = [:] } - headers?.merge(configuration.headers ?? [:], uniquingKeysWith: { (old, _) in old }) - headers = try handleMiddlewareHeadersBeforeSendIfNeeded(headers: headers) } diff --git a/Source/Session.swift b/Source/Session.swift index 139137b1..a0cedbda 100644 --- a/Source/Session.swift +++ b/Source/Session.swift @@ -1,6 +1,6 @@ // Session.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/SessionTaskFactory.swift b/Source/SessionTaskFactory.swift index ea2b2ced..272c91de 100644 --- a/Source/SessionTaskFactory.swift +++ b/Source/SessionTaskFactory.swift @@ -1,6 +1,6 @@ // SessionTaskFactory.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/SwiftUI/Image.swift b/Source/SwiftUI/Image.swift index c21a2cba..736ae9f2 100644 --- a/Source/SwiftUI/Image.swift +++ b/Source/SwiftUI/Image.swift @@ -1,6 +1,6 @@ // Image.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Source/TNError.swift b/Source/TNError.swift index d6e5ca56..10343251 100644 --- a/Source/TNError.swift +++ b/Source/TNError.swift @@ -1,6 +1,6 @@ // TNError.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -26,7 +26,7 @@ public enum TNError: Error { /// Thrown when the url is not valid. case invalidURL /// Thrown when the environment is not set. - case environmenotSet + case environmentNotSet /// Thrown when the params contain invalid characters. case invalidParams /// Thrown when the response object is expected to be a UIImage but it's not. @@ -77,7 +77,7 @@ extension TNError: LocalizedError { switch self { case .invalidURL: return NSLocalizedString("The URL is invalid", comment: "TNError") - case .environmenotSet: + case .environmentNotSet: return NSLocalizedString("Environment not set, add the 'Environment.set()' method call in your AppDelegate application(_:didFinishLaunchingWithOptions:) method.", comment: "TNError") case .invalidParams: return NSLocalizedString("The parameters are not valid", comment: "TNError") diff --git a/Source/Types.swift b/Source/Types.swift index a63f1d2a..9d4652df 100644 --- a/Source/Types.swift +++ b/Source/Types.swift @@ -1,6 +1,6 @@ // Types.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/TermiNetwork.xcodeproj/project.pbxproj b/TermiNetwork.xcodeproj/project.pbxproj index a0ae78a6..00cdfd83 100644 --- a/TermiNetwork.xcodeproj/project.pbxproj +++ b/TermiNetwork.xcodeproj/project.pbxproj @@ -17,7 +17,7 @@ 23ACE26B2932371100BA45D5 /* www.billp.dev.cer in Resources */ = {isa = PBXBuildFile; fileRef = 2332504629251BC30082EDC7 /* www.billp.dev.cer */; }; 23B36A0D277BB6D100A270B7 /* CryptoSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 23B36A0C277BB6D100A270B7 /* CryptoSwift */; }; F309C0ED25A512AB00D10877 /* Request+ResponseTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = F309C0EC25A512AB00D10877 /* Request+ResponseTypes.swift */; }; - F30A298A258787320046C8E6 /* MiscRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A2989258787320046C8E6 /* MiscRoute.swift */; }; + F30A298A258787320046C8E6 /* MiscRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A2989258787320046C8E6 /* MiscRepository.swift */; }; F30A298E2587881D0046C8E6 /* RSEncryptedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A298D258788180046C8E6 /* RSEncryptedModel.swift */; }; F30A29922587884B0046C8E6 /* EncryptedModelTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A29912587884B0046C8E6 /* EncryptedModelTransformer.swift */; }; F30A2998258788880046C8E6 /* EncryptedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A2997258788880046C8E6 /* EncryptedModel.swift */; }; @@ -28,7 +28,7 @@ F31126AD257A563600775D7E /* FileResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = F31126AC257A563600775D7E /* FileResponse.swift */; }; F3116AA42460A04B00DFE453 /* RequestBodyGenerators.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3116AA22460A04B00DFE453 /* RequestBodyGenerators.swift */; }; F3116AA52460A04B00DFE453 /* RequestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3116AA32460A04B00DFE453 /* RequestHelpers.swift */; }; - F3116AA92460A06600DFE453 /* RouteProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3116AA72460A06600DFE453 /* RouteProtocol.swift */; }; + F3116AA92460A06600DFE453 /* EndpointProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3116AA72460A06600DFE453 /* EndpointProtocol.swift */; }; F3116AAA2460A06600DFE453 /* RequestMiddlewareProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3116AA82460A06600DFE453 /* RequestMiddlewareProtocol.swift */; }; F3116AB62460A09E00DFE453 /* UIImageView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3116AAC2460A09E00DFE453 /* UIImageView+Extensions.swift */; }; F3116AB82460A09E00DFE453 /* Request+Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3116AAE2460A09E00DFE453 /* Request+Mock.swift */; }; @@ -85,12 +85,12 @@ F3850C88243D103700F7CC13 /* Env.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C7A243D103700F7CC13 /* Env.swift */; }; F3850C89243D103700F7CC13 /* TestQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C7B243D103700F7CC13 /* TestQueue.swift */; }; F3850C8A243D103700F7CC13 /* TestEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C7C243D103700F7CC13 /* TestEnvironment.swift */; }; - F3850C8B243D103700F7CC13 /* APIRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C7D243D103700F7CC13 /* APIRoute.swift */; }; + F3850C8B243D103700F7CC13 /* TestRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C7D243D103700F7CC13 /* TestRepository.swift */; }; F3850C8C243D103700F7CC13 /* TestParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C7F243D103700F7CC13 /* TestParams.swift */; }; F3850C8D243D103700F7CC13 /* TestJSONParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C80243D103700F7CC13 /* TestJSONParams.swift */; }; F3850C8E243D103700F7CC13 /* TestHeaders.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C81243D103700F7CC13 /* TestHeaders.swift */; }; F3850C93243D103700F7CC13 /* TestTNErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C86243D103700F7CC13 /* TestTNErrors.swift */; }; - F3850CA6243D104900F7CC13 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C96243D104900F7CC13 /* Router.swift */; }; + F3850CA6243D104900F7CC13 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C96243D104900F7CC13 /* Client.swift */; }; F3850CA8243D104900F7CC13 /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C98243D104900F7CC13 /* Session.swift */; }; F3850CAA243D104900F7CC13 /* Path.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C9A243D104900F7CC13 /* Path.swift */; }; F3850CAB243D104900F7CC13 /* TNError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3850C9B243D104900F7CC13 /* TNError.swift */; }; @@ -112,7 +112,7 @@ F398575225AC945A00DCCAAE /* TestMockedRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F398575125AC945A00DCCAAE /* TestMockedRequest.swift */; }; F3A0BC0F25769385005139D5 /* DemoEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A0BC07257692E6005139D5 /* DemoEnvironment.swift */; }; F3A0BC1825769434005139D5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A0BC12257693D2005139D5 /* AppDelegate.swift */; }; - F3A0BC1C25769453005139D5 /* CityRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A0BC1B25769453005139D5 /* CityRoute.swift */; }; + F3A0BC1C25769453005139D5 /* CitiesRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A0BC1B25769453005139D5 /* CitiesRepository.swift */; }; F3A0BC24257694F7005139D5 /* RSCity.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A0BC23257694F7005139D5 /* RSCity.swift */; }; F3A0E84A25AB8F8A00A81DDD /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A0E84925AB8F8A00A81DDD /* Types.swift */; }; F3A4B14825968ED0004812B6 /* Request+NSCopying.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3A4B14725968ED0004812B6 /* Request+NSCopying.swift */; }; @@ -122,7 +122,7 @@ F3AF556925987256000E01D8 /* DoNothingInterceptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3AF556825987256000E01D8 /* DoNothingInterceptor.swift */; }; F3D16EC82575299900F7B523 /* TermiNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F319682D243D01E1008725CE /* TermiNetwork.framework */; }; F3D16EC92575299900F7B523 /* TermiNetwork.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F319682D243D01E1008725CE /* TermiNetwork.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - F3F255E9244C33B800517BF7 /* RouteConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F255E8244C33B800517BF7 /* RouteConfiguration.swift */; }; + F3F255E9244C33B800517BF7 /* EndpointConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F255E8244C33B800517BF7 /* EndpointConfiguration.swift */; }; F3F48288245EBF6D00656449 /* TestUploadOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F48287245EBE8000656449 /* TestUploadOperations.swift */; }; F3F4828D245EE58C00656449 /* MultipartFormDataStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F4828C245EE58C00656449 /* MultipartFormDataStream.swift */; }; F3F9709525758C0B0045138A /* CityExplorerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F9709425758C0B0045138A /* CityExplorerView.swift */; }; @@ -169,7 +169,7 @@ 23B36A07277BB5B800A270B7 /* CryptoKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CryptoKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.2.sdk/System/Library/Frameworks/CryptoKit.framework; sourceTree = DEVELOPER_DIR; }; F309C0EC25A512AB00D10877 /* Request+ResponseTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Request+ResponseTypes.swift"; sourceTree = ""; }; F30A2986258783B40046C8E6 /* CryptoMiddleware.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoMiddleware.swift; sourceTree = ""; }; - F30A2989258787320046C8E6 /* MiscRoute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MiscRoute.swift; sourceTree = ""; }; + F30A2989258787320046C8E6 /* MiscRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MiscRepository.swift; sourceTree = ""; }; F30A298D258788180046C8E6 /* RSEncryptedModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSEncryptedModel.swift; sourceTree = ""; }; F30A29912587884B0046C8E6 /* EncryptedModelTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedModelTransformer.swift; sourceTree = ""; }; F30A2997258788880046C8E6 /* EncryptedModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedModel.swift; sourceTree = ""; }; @@ -179,7 +179,7 @@ F31126AC257A563600775D7E /* FileResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileResponse.swift; sourceTree = ""; }; F3116AA22460A04B00DFE453 /* RequestBodyGenerators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestBodyGenerators.swift; sourceTree = ""; }; F3116AA32460A04B00DFE453 /* RequestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestHelpers.swift; sourceTree = ""; }; - F3116AA72460A06600DFE453 /* RouteProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RouteProtocol.swift; sourceTree = ""; }; + F3116AA72460A06600DFE453 /* EndpointProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndpointProtocol.swift; sourceTree = ""; }; F3116AA82460A06600DFE453 /* RequestMiddlewareProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestMiddlewareProtocol.swift; sourceTree = ""; }; F3116AAC2460A09E00DFE453 /* UIImageView+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImageView+Extensions.swift"; sourceTree = ""; }; F3116AAE2460A09E00DFE453 /* Request+Mock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Request+Mock.swift"; sourceTree = ""; }; @@ -240,13 +240,13 @@ F3850C7A243D103700F7CC13 /* Env.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Env.swift; sourceTree = ""; }; F3850C7B243D103700F7CC13 /* TestQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestQueue.swift; sourceTree = ""; }; F3850C7C243D103700F7CC13 /* TestEnvironment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestEnvironment.swift; sourceTree = ""; }; - F3850C7D243D103700F7CC13 /* APIRoute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APIRoute.swift; sourceTree = ""; }; + F3850C7D243D103700F7CC13 /* TestRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestRepository.swift; sourceTree = ""; }; F3850C7F243D103700F7CC13 /* TestParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestParams.swift; sourceTree = ""; }; F3850C80243D103700F7CC13 /* TestJSONParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestJSONParams.swift; sourceTree = ""; }; F3850C81243D103700F7CC13 /* TestHeaders.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestHeaders.swift; sourceTree = ""; }; F3850C85243D103700F7CC13 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; F3850C86243D103700F7CC13 /* TestTNErrors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestTNErrors.swift; sourceTree = ""; }; - F3850C96243D104900F7CC13 /* Router.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = ""; }; + F3850C96243D104900F7CC13 /* Client.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; F3850C98243D104900F7CC13 /* Session.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Session.swift; sourceTree = ""; }; F3850C9A243D104900F7CC13 /* Path.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Path.swift; sourceTree = ""; }; F3850C9B243D104900F7CC13 /* TNError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TNError.swift; sourceTree = ""; }; @@ -270,7 +270,7 @@ F398575125AC945A00DCCAAE /* TestMockedRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestMockedRequest.swift; sourceTree = ""; }; F3A0BC07257692E6005139D5 /* DemoEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoEnvironment.swift; sourceTree = ""; }; F3A0BC12257693D2005139D5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - F3A0BC1B25769453005139D5 /* CityRoute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CityRoute.swift; sourceTree = ""; }; + F3A0BC1B25769453005139D5 /* CitiesRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CitiesRepository.swift; sourceTree = ""; }; F3A0BC23257694F7005139D5 /* RSCity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSCity.swift; sourceTree = ""; }; F3A0E84925AB8F8A00A81DDD /* Types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Types.swift; sourceTree = ""; }; F3A4B14725968ED0004812B6 /* Request+NSCopying.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Request+NSCopying.swift"; sourceTree = ""; }; @@ -278,7 +278,7 @@ F3AA5131256EA13E00D64D31 /* FileStreamer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileStreamer.swift; sourceTree = ""; }; F3AA5146256EF53000D64D31 /* TestHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHelpers.swift; sourceTree = ""; }; F3AF556825987256000E01D8 /* DoNothingInterceptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoNothingInterceptor.swift; sourceTree = ""; }; - F3F255E8244C33B800517BF7 /* RouteConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouteConfiguration.swift; sourceTree = ""; }; + F3F255E8244C33B800517BF7 /* EndpointConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndpointConfiguration.swift; sourceTree = ""; }; F3F48287245EBE8000656449 /* TestUploadOperations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestUploadOperations.swift; sourceTree = ""; }; F3F4828C245EE58C00656449 /* MultipartFormDataStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipartFormDataStream.swift; sourceTree = ""; }; F3F9709425758C0B0045138A /* CityExplorerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CityExplorerView.swift; sourceTree = ""; }; @@ -355,7 +355,7 @@ F3116AA62460A06600DFE453 /* Protocols */ = { isa = PBXGroup; children = ( - F3116AA72460A06600DFE453 /* RouteProtocol.swift */, + F3116AA72460A06600DFE453 /* EndpointProtocol.swift */, F3116AA82460A06600DFE453 /* RequestMiddlewareProtocol.swift */, F32195B225782E1A000941F1 /* InterceptorProtocol.swift */, ); @@ -614,8 +614,8 @@ F3850CA3243D104900F7CC13 /* Environment.swift */, F3850CA0243D104900F7CC13 /* Request.swift */, F3850C9E243D104900F7CC13 /* Configuration.swift */, - F3850C96243D104900F7CC13 /* Router.swift */, - F3F255E8244C33B800517BF7 /* RouteConfiguration.swift */, + F3850C96243D104900F7CC13 /* Client.swift */, + F3F255E8244C33B800517BF7 /* EndpointConfiguration.swift */, F3850C9F243D104900F7CC13 /* Queue.swift */, F3850C98243D104900F7CC13 /* Session.swift */, F3850C9B243D104900F7CC13 /* TNError.swift */, @@ -659,7 +659,7 @@ isa = PBXGroup; children = ( F3850C7A243D103700F7CC13 /* Env.swift */, - F3850C7D243D103700F7CC13 /* APIRoute.swift */, + F3850C7D243D103700F7CC13 /* TestRepository.swift */, ); name = Communication; sourceTree = ""; @@ -679,19 +679,19 @@ F3A0BC22257694E2005139D5 /* Models */, F30A2985258783970046C8E6 /* Middleware */, F31F8890257A807300D9A802 /* Transformers */, - F3A0BC21257694DC005139D5 /* Routers */, + F3A0BC21257694DC005139D5 /* Repositories */, F3A0BC07257692E6005139D5 /* DemoEnvironment.swift */, ); path = Communication; sourceTree = ""; }; - F3A0BC21257694DC005139D5 /* Routers */ = { + F3A0BC21257694DC005139D5 /* Repositories */ = { isa = PBXGroup; children = ( - F3A0BC1B25769453005139D5 /* CityRoute.swift */, - F30A2989258787320046C8E6 /* MiscRoute.swift */, + F3A0BC1B25769453005139D5 /* CitiesRepository.swift */, + F30A2989258787320046C8E6 /* MiscRepository.swift */, ); - path = Routers; + path = Repositories; sourceTree = ""; }; F3A0BC22257694E2005139D5 /* Models */ = { @@ -947,7 +947,7 @@ files = ( F3850CA8243D104900F7CC13 /* Session.swift in Sources */, F3850CAD243D104900F7CC13 /* Log.swift in Sources */, - F3116AA92460A06600DFE453 /* RouteProtocol.swift in Sources */, + F3116AA92460A06600DFE453 /* EndpointProtocol.swift in Sources */, F3A0E84A25AB8F8A00A81DDD /* Types.swift in Sources */, F3116AB82460A09E00DFE453 /* Request+Mock.swift in Sources */, F31F88B4257C056200D9A802 /* Cache.swift in Sources */, @@ -956,7 +956,7 @@ F3F4828D245EE58C00656449 /* MultipartFormDataStream.swift in Sources */, F3116ABA2460A09E00DFE453 /* Request+FileOperations.swift in Sources */, F3116ABE2460A09E00DFE453 /* Data+Extensions.swift in Sources */, - F3850CA6243D104900F7CC13 /* Router.swift in Sources */, + F3850CA6243D104900F7CC13 /* Client.swift in Sources */, F33ACF4D2587F904004DAC46 /* Request+ResponseHeaders.swift in Sources */, F3850CAF243D104900F7CC13 /* Queue.swift in Sources */, F3116ABC2460A09E00DFE453 /* Request+Middleware.swift in Sources */, @@ -967,7 +967,7 @@ F373779225C4B4720075EFA3 /* Reachability.swift in Sources */, F3116AAA2460A06600DFE453 /* RequestMiddlewareProtocol.swift in Sources */, F31F88A8257AD39400D9A802 /* Image.swift in Sources */, - F3F255E9244C33B800517BF7 /* RouteConfiguration.swift in Sources */, + F3F255E9244C33B800517BF7 /* EndpointConfiguration.swift in Sources */, F3850CB0243D104900F7CC13 /* Request.swift in Sources */, F3116AA42460A04B00DFE453 /* RequestBodyGenerators.swift in Sources */, F3850CAB243D104900F7CC13 /* TNError.swift in Sources */, @@ -1007,7 +1007,7 @@ F32BB57725A8A47E00E6E096 /* StatusCode.swift in Sources */, F32195BD25783F29000941F1 /* GlobalInterceptor.swift in Sources */, F3556065257401330047D46D /* TestDownloadOperations.swift in Sources */, - F3850C8B243D103700F7CC13 /* APIRoute.swift in Sources */, + F3850C8B243D103700F7CC13 /* TestRepository.swift in Sources */, F3850C8A243D103700F7CC13 /* TestEnvironment.swift in Sources */, F333429A25792E9D0087BDBA /* ErrorModel.swift in Sources */, F3850C8C243D103700F7CC13 /* TestParams.swift in Sources */, @@ -1037,7 +1037,7 @@ buildActionMask = 2147483647; files = ( F355608D257527C40047D46D /* ContentView.swift in Sources */, - F3A0BC1C25769453005139D5 /* CityRoute.swift in Sources */, + F3A0BC1C25769453005139D5 /* CitiesRepository.swift in Sources */, F38F34A225896ED500D5BB17 /* FileUploaderUtils.swift in Sources */, F31F88CE257CCF6F00D9A802 /* ServiceErrorInterceptor.swift in Sources */, F363508225894AC6002AF5DE /* FileUploader.swift in Sources */, @@ -1046,7 +1046,7 @@ F30A299B25878C5F0046C8E6 /* CryptoMiddleware.swift in Sources */, F31F88A4257A816400D9A802 /* City.swift in Sources */, F31F88D9257CDAFA00D9A802 /* DemoApp.swift in Sources */, - F30A298A258787320046C8E6 /* MiscRoute.swift in Sources */, + F30A298A258787320046C8E6 /* MiscRepository.swift in Sources */, F3A0BC0F25769385005139D5 /* DemoEnvironment.swift in Sources */, F33ACF5B25880A5E004DAC46 /* FileDownloader.swift in Sources */, F38F349225896AFF00D5BB17 /* FileUploadTransformer.swift in Sources */, @@ -1322,7 +1322,7 @@ DEVELOPMENT_TEAM = 899S8YHUCE; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = "Examples/Supporting Files/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1345,7 +1345,7 @@ DEVELOPMENT_TEAM = 899S8YHUCE; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = "Examples/Supporting Files/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/TermiNetwork/TermiNetwork.h b/TermiNetwork/TermiNetwork.h index 4a91dd31..d6a89587 100644 --- a/TermiNetwork/TermiNetwork.h +++ b/TermiNetwork/TermiNetwork.h @@ -1,6 +1,6 @@ // TermiNetwork.h // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/CryptoMiddleware.swift b/Tests/CryptoMiddleware.swift index 82d3c9f6..de40ee9f 100644 --- a/Tests/CryptoMiddleware.swift +++ b/Tests/CryptoMiddleware.swift @@ -1,6 +1,6 @@ // CryptoMiddleware.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/DoNothingInterceptor.swift b/Tests/DoNothingInterceptor.swift index 93ac1bb1..c3cf7e3e 100644 --- a/Tests/DoNothingInterceptor.swift +++ b/Tests/DoNothingInterceptor.swift @@ -1,6 +1,6 @@ // GlobalInterceptor.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/Env.swift b/Tests/Env.swift index 256638be..5e556a3f 100644 --- a/Tests/Env.swift +++ b/Tests/Env.swift @@ -1,6 +1,6 @@ // Env.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/GlobalInterceptor.swift b/Tests/GlobalInterceptor.swift index c615d2e5..3aefb4c2 100644 --- a/Tests/GlobalInterceptor.swift +++ b/Tests/GlobalInterceptor.swift @@ -1,6 +1,6 @@ // GlobalInterceptor.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/MockData.bundle/main-router/headers.json b/Tests/MockData.bundle/main-repo/headers.json similarity index 100% rename from Tests/MockData.bundle/main-router/headers.json rename to Tests/MockData.bundle/main-repo/headers.json diff --git a/Tests/Models/Domain/TestModel.swift b/Tests/Models/Domain/TestModel.swift index 3bd27c9b..bfbb81e0 100644 --- a/Tests/Models/Domain/TestModel.swift +++ b/Tests/Models/Domain/TestModel.swift @@ -1,6 +1,6 @@ // TestModel.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/Models/Rest/EncryptedModel.swift b/Tests/Models/Rest/EncryptedModel.swift index 37b1d452..328087ab 100644 --- a/Tests/Models/Rest/EncryptedModel.swift +++ b/Tests/Models/Rest/EncryptedModel.swift @@ -1,6 +1,6 @@ // EncryptedModel.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/Models/Rest/ErrorModel.swift b/Tests/Models/Rest/ErrorModel.swift index ab609600..467d17a4 100644 --- a/Tests/Models/Rest/ErrorModel.swift +++ b/Tests/Models/Rest/ErrorModel.swift @@ -1,6 +1,6 @@ // ErrorModel.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/Models/Rest/FileResponse.swift b/Tests/Models/Rest/FileResponse.swift index fd69e62a..ae6cd6e0 100644 --- a/Tests/Models/Rest/FileResponse.swift +++ b/Tests/Models/Rest/FileResponse.swift @@ -1,6 +1,6 @@ // FileResponse.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/Models/Rest/StatusCode.swift b/Tests/Models/Rest/StatusCode.swift index 1bfbb71b..4b859907 100644 --- a/Tests/Models/Rest/StatusCode.swift +++ b/Tests/Models/Rest/StatusCode.swift @@ -1,6 +1,6 @@ // StatusCode.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/Models/Rest/TestHeaders.swift b/Tests/Models/Rest/TestHeaders.swift index 13fdfd89..42c5ffb2 100644 --- a/Tests/Models/Rest/TestHeaders.swift +++ b/Tests/Models/Rest/TestHeaders.swift @@ -1,6 +1,6 @@ // Queue.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/Models/Rest/TestJSONParams.swift b/Tests/Models/Rest/TestJSONParams.swift index cb2a2a6d..15b1821e 100644 --- a/Tests/Models/Rest/TestJSONParams.swift +++ b/Tests/Models/Rest/TestJSONParams.swift @@ -1,6 +1,6 @@ // Queue.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/Models/Rest/TestParams.swift b/Tests/Models/Rest/TestParams.swift index 5a4f2607..85cdee11 100644 --- a/Tests/Models/Rest/TestParams.swift +++ b/Tests/Models/Rest/TestParams.swift @@ -1,6 +1,6 @@ // Queue.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/StatusCodeTransformer.swift b/Tests/StatusCodeTransformer.swift index 8db96d1c..1874608e 100644 --- a/Tests/StatusCodeTransformer.swift +++ b/Tests/StatusCodeTransformer.swift @@ -1,6 +1,6 @@ // TestTransformer.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/TestCache.swift b/Tests/TestCache.swift index fc6ef84f..7f761f19 100644 --- a/Tests/TestCache.swift +++ b/Tests/TestCache.swift @@ -1,6 +1,6 @@ // TestCache.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/TestConfiguration.swift b/Tests/TestConfiguration.swift index 975786f0..2001b4cf 100644 --- a/Tests/TestConfiguration.swift +++ b/Tests/TestConfiguration.swift @@ -1,6 +1,6 @@ // TestConfiguration.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -50,7 +50,7 @@ class TestConfiguration: XCTestCase { return conf }() - static var routeConfiguration: Configuration = { + static var repositoryConfiguration: Configuration = { let conf = Configuration() conf.verbose = false conf.cachePolicy = .returnCacheDataDontLoad @@ -78,9 +78,7 @@ class TestConfiguration: XCTestCase { } } - var router: Router { - return Router() - } + lazy var client: Client = .init() override func setUp() { super.setUp() @@ -94,7 +92,7 @@ class TestConfiguration: XCTestCase { } func testEnvConfiguration() { - let request = router.request(for: .testHeaders) + let request = client.request(for: .testHeaders) let reqConf = request.configuration XCTAssert(reqConf.verbose == TestConfiguration.envConfiguration.verbose) @@ -123,7 +121,7 @@ class TestConfiguration: XCTestCase { Environment.set(environmentObject: Environment(url: "http://www.google.com/abc/def", configuration: TestConfiguration.envConfiguration)) - let request = router.request(for: .testHeaders) + let request = client.request(for: .testHeaders) let reqConf = request.configuration XCTAssert(reqConf.verbose == TestConfiguration.envConfiguration.verbose) @@ -148,23 +146,23 @@ class TestConfiguration: XCTestCase { .requestMiddleware.map { String(describing: $0) })) } - func testRouteConfiguration() { - let request = router.request(for: - .testConfigurationParameterized(conf: TestConfiguration.routeConfiguration)) + func testEndpointConfiguration() { + let request = client.request(for: + .testConfigurationParameterized(conf: TestConfiguration.repositoryConfiguration)) let reqConf = request.configuration - let routeConf = TestConfiguration.routeConfiguration + let endpointConf = TestConfiguration.repositoryConfiguration var allHeaders = TestConfiguration.envConfiguration.headers ?? [:] - let routeHeaders = routeConf.headers ?? [:] + let endpointHeaders = endpointConf.headers ?? [:] - allHeaders.merge(routeHeaders, uniquingKeysWith: { _, new in new}) + allHeaders.merge(endpointHeaders, uniquingKeysWith: { _, new in new}) - XCTAssert(reqConf.verbose == routeConf.verbose) - XCTAssert(reqConf.cachePolicy == routeConf.cachePolicy) - XCTAssert(reqConf.timeoutInterval == routeConf.timeoutInterval) - XCTAssert(reqConf.requestBodyType == routeConf.requestBodyType) - XCTAssert(reqConf.certificatePaths == routeConf.certificatePaths) - XCTAssert(reqConf.verbose == routeConf.verbose) + XCTAssert(reqConf.verbose == endpointConf.verbose) + XCTAssert(reqConf.cachePolicy == endpointConf.cachePolicy) + XCTAssert(reqConf.timeoutInterval == endpointConf.timeoutInterval) + XCTAssert(reqConf.requestBodyType == endpointConf.requestBodyType) + XCTAssert(reqConf.certificatePaths == endpointConf.certificatePaths) + XCTAssert(reqConf.verbose == endpointConf.verbose) XCTAssert(reqConf.headers == allHeaders) if case .useDefaultKeys = reqConf.keyDecodingStrategy { XCTAssert(true) @@ -172,8 +170,8 @@ class TestConfiguration: XCTestCase { XCTAssert(false) } XCTAssert(Set(arrayLiteral: reqConf.interceptors.map { String(describing: $0) }) == - Set(arrayLiteral: routeConf.interceptors.map { String(describing: $0) })) + Set(arrayLiteral: endpointConf.interceptors.map { String(describing: $0) })) XCTAssert(Set(arrayLiteral: reqConf.requestMiddleware.map { String(describing: $0) }) == - Set(arrayLiteral: routeConf.requestMiddleware.map { String(describing: $0) })) + Set(arrayLiteral: endpointConf.requestMiddleware.map { String(describing: $0) })) } } diff --git a/Tests/TestDownloadOperations.swift b/Tests/TestDownloadOperations.swift index 4777e63c..6148d95d 100644 --- a/Tests/TestDownloadOperations.swift +++ b/Tests/TestDownloadOperations.swift @@ -1,6 +1,6 @@ // TestDownloadOperations.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -26,8 +26,8 @@ class TestDownloadOperations: XCTestCase { verbose: true) }() - lazy var router: Router = { - return Router(environment: Env.termiNetworkRemote, + lazy var client: Client = { + return Client(environment: Env.termiNetworkRemote, configuration: configuration) }() @@ -60,7 +60,7 @@ class TestDownloadOperations: XCTestCase { try? FileManager.default.removeItem(at: cacheURL) - router.request(for: .fileDownload) + client.request(for: .fileDownload) .download(destinationPath: cacheURL.path, progressUpdate: { bytesSent, totalBytes, progress in if bytesSent == totalBytes && progress == 1 { @@ -89,7 +89,7 @@ class TestDownloadOperations: XCTestCase { var failed = true - router.request(for: .fileDownload) + client.request(for: .fileDownload) .download(destinationPath: "", progressUpdate: { bytesSent, totalBytes, progress in if bytesSent == totalBytes && progress == 1 { diff --git a/Tests/TestDownloadOperationsAsync.swift b/Tests/TestDownloadOperationsAsync.swift index 926bbb9e..7540d95c 100644 --- a/Tests/TestDownloadOperationsAsync.swift +++ b/Tests/TestDownloadOperationsAsync.swift @@ -1,6 +1,6 @@ // TestDownloadOperationsAsync.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -26,9 +26,9 @@ class TestDownloadOperationsAsync: XCTestCase { verbose: true) }() - lazy var router: Router = { - return Router(environment: Env.termiNetworkRemote, - configuration: configuration) + lazy var client: Client = { + return .init(environment: Env.termiNetworkRemote, + configuration: configuration) }() override func setUp() { @@ -59,7 +59,7 @@ class TestDownloadOperationsAsync: XCTestCase { try? FileManager.default.removeItem(at: cacheURL) do { - try await router.request(for: .fileDownload) + try await client.request(for: .fileDownload) .asyncDownload(destinationPath: cacheURL.path, progressUpdate: { bytesSent, totalBytes, progress in if bytesSent == totalBytes && progress == 1 { @@ -91,7 +91,7 @@ class TestDownloadOperationsAsync: XCTestCase { try? FileManager.default.removeItem(at: cacheURL) do { - try await router.request(for: .fileDownload) + try await client.request(for: .fileDownload) .asyncDownload(destinationPath: cacheURL.path, progressUpdate: { bytesSent, totalBytes, progress in if bytesSent == totalBytes && progress == 1 { @@ -121,7 +121,7 @@ class TestDownloadOperationsAsync: XCTestCase { var failed = true do { - try await router.request(for: .fileDownload) + try await client.request(for: .fileDownload) .asyncDownload(destinationPath: "", progressUpdate: { bytesSent, totalBytes, progress in if bytesSent == totalBytes && progress == 1 { diff --git a/Tests/TestEnvironment.swift b/Tests/TestEnvironment.swift index 87964eb4..dcbcaec9 100644 --- a/Tests/TestEnvironment.swift +++ b/Tests/TestEnvironment.swift @@ -1,6 +1,6 @@ // TestEnvironment.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/TestExtensions.swift b/Tests/TestExtensions.swift index 708808cc..59389541 100644 --- a/Tests/TestExtensions.swift +++ b/Tests/TestExtensions.swift @@ -1,6 +1,6 @@ // TestExtensions.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/TestHelpers.swift b/Tests/TestHelpers.swift index 035a1890..92af09b4 100644 --- a/Tests/TestHelpers.swift +++ b/Tests/TestHelpers.swift @@ -1,6 +1,6 @@ // TestHelpers.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/TestInterceptors.swift b/Tests/TestInterceptors.swift index fa8b319c..9a31ecd5 100644 --- a/Tests/TestInterceptors.swift +++ b/Tests/TestInterceptors.swift @@ -1,6 +1,6 @@ // TestInterceptors.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -21,11 +21,11 @@ import XCTest import TermiNetwork class TestInterceptors: XCTestCase { - lazy var router: Router = { + lazy var client: Client = { let configuration = Configuration() configuration.interceptors = [GlobalInterceptor.self] configuration.verbose = true - return Router(configuration: configuration) + return Client(configuration: configuration) }() override func setUp() { @@ -45,7 +45,7 @@ class TestInterceptors: XCTestCase { let expectation = XCTestExpectation(description: "testInterceptorContinue") var failed = true - router.request(for: .testPostParams(value1: false, + client.request(for: .testPostParams(value1: false, value2: 1, value3: 2, value4: "", @@ -70,7 +70,7 @@ class TestInterceptors: XCTestCase { let expectation = XCTestExpectation(description: "testInterceptorRetry") var failed = true - router.request(for: .testPostParams(value1: false, + client.request(for: .testPostParams(value1: false, value2: 1, value3: 2, value4: "", @@ -106,7 +106,7 @@ class TestInterceptors: XCTestCase { var progressSucceded = false var successCount = 0 - router.request(for: .fileUpload(url: url, param: "test")) + client.request(for: .fileUpload(url: url, param: "test")) .upload(responseType: FileResponse.self, progressUpdate: { bytesSent, totalBytes, progress in if bytesSent == totalBytes && progress == 1 { @@ -145,7 +145,7 @@ class TestInterceptors: XCTestCase { try? FileManager.default.removeItem(at: cacheURL) - router.request(for: .fileDownload) + client.request(for: .fileDownload) .download(destinationPath: cacheURL.path, progressUpdate: { bytesSent, totalBytes, progress in if bytesSent == totalBytes && progress == 1 { @@ -174,10 +174,10 @@ class TestInterceptors: XCTestCase { let expectation = XCTestExpectation(description: "testMultipleInterceptors") var failed = true - router.configuration?.interceptors?.append(DoNothingInterceptor.self) - router.configuration?.cachePolicy = .reloadIgnoringLocalCacheData + client.configuration?.interceptors?.append(DoNothingInterceptor.self) + client.configuration?.cachePolicy = .reloadIgnoringLocalCacheData - let request = router.request(for: .testPostParams(value1: false, + let request = client.request(for: .testPostParams(value1: false, value2: 1, value3: 2, value4: "", @@ -195,7 +195,7 @@ class TestInterceptors: XCTestCase { wait(for: [expectation], timeout: 60) - router.configuration?.interceptors?.removeLast() + client.configuration?.interceptors?.removeLast() XCTAssert(!failed) } @@ -206,13 +206,13 @@ class TestInterceptors: XCTestCase { let expectation = XCTestExpectation(description: "testUnauthorizedInterceptor") var failed = true - router.configuration?.interceptors = [UnauthorizedInterceptor.self] - router.configuration?.cachePolicy = .reloadIgnoringLocalCacheData + client.configuration?.interceptors = [UnauthorizedInterceptor.self] + client.configuration?.cachePolicy = .reloadIgnoringLocalCacheData let authValue = UnauthorizedInterceptor.authorizationValue - let request = router.request(for: .testStatusCode(code: 401)) + let request = client.request(for: .testStatusCode(code: 401)) request.success(responseType: Data.self) { _ in - let dummyRequest = try? self.router.request(for: .testStatusCode(code: 200)).asRequest() + let dummyRequest = try? self.client.request(for: .testStatusCode(code: 200)).asRequest() failed = !( Environment.current.configuration?.headers?["Authorization"] == authValue && request.headers?["Authorization"] == authValue && @@ -228,7 +228,7 @@ class TestInterceptors: XCTestCase { wait(for: [expectation], timeout: 180) - router.configuration?.interceptors?.removeLast() + client.configuration?.interceptors?.removeLast() XCTAssert(!failed) } diff --git a/Tests/TestMockedRequest.swift b/Tests/TestMockedRequest.swift index b0089586..04ab0a48 100644 --- a/Tests/TestMockedRequest.swift +++ b/Tests/TestMockedRequest.swift @@ -1,6 +1,6 @@ // TestMockRequests.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -69,13 +69,8 @@ class TestMockedRequests: XCTestCase { } } - var router: Router { - return Router() - } - - var router2: Router { - return Router(configuration: TestMockedRequests.mockDelayConfiguration) - } + lazy var client: Client = .init() + lazy var client2: Client = .init(configuration: Self.mockDelayConfiguration) override func setUp() { super.setUp() @@ -92,7 +87,7 @@ class TestMockedRequests: XCTestCase { let expectation = XCTestExpectation(description: "testEnvConfiguration") var failed = true - router.request(for: .testHeaders) + client.request(for: .testHeaders) .success(responseType: TestHeaders.self) { response in failed = !(response.customHeader == "yo man!!!!") expectation.fulfill() @@ -116,7 +111,7 @@ class TestMockedRequests: XCTestCase { } for _ in 0..<100 { - let req = router2.request(for: .testHeaders) + let req = client2.request(for: .testHeaders) req.configuration.verbose = false req.queue(queue) .success(responseType: TestHeaders.self) { response in @@ -137,7 +132,7 @@ class TestMockedRequests: XCTestCase { let expectation = XCTestExpectation(description: "testMockFailed") var failed = true - let req = router2.request(for: .testOverrideHeaders) + let req = client2.request(for: .testOverrideHeaders) req.configuration.verbose = false req.success(responseType: TestHeaders.self) { _ in failed = true diff --git a/Tests/TestPinning.swift b/Tests/TestPinning.swift index 4a605019..1c0c6c05 100644 --- a/Tests/TestPinning.swift +++ b/Tests/TestPinning.swift @@ -1,6 +1,6 @@ // TestPinning.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -55,7 +55,7 @@ class TestPinning: XCTestCase { let expectation = XCTestExpectation(description: "testValidCertificate") var failed = true - Request(route: APIRoute.testPinning(certPath: validCertPath)) + Request(endpoint: TestRepository.testPinning(certPath: validCertPath)) .success(responseType: String.self) { _ in failed = false expectation.fulfill() @@ -74,7 +74,7 @@ class TestPinning: XCTestCase { let expectation = XCTestExpectation(description: "testInvalidCertificate") var failed = true - Request(route: APIRoute.testPinning(certPath: invalidCertPath)) + Request(endpoint: TestRepository.testPinning(certPath: invalidCertPath)) .success(responseType: String.self) { _ in failed = true expectation.fulfill() diff --git a/Tests/TestQueue.swift b/Tests/TestQueue.swift index 9ac69004..20c7ebde 100644 --- a/Tests/TestQueue.swift +++ b/Tests/TestQueue.swift @@ -1,6 +1,6 @@ // TestQueue.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/TestReachability.swift b/Tests/TestReachability.swift index e3bdaba3..f1974127 100644 --- a/Tests/TestReachability.swift +++ b/Tests/TestReachability.swift @@ -1,6 +1,6 @@ // TestReachability.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/APIRoute.swift b/Tests/TestRepository.swift similarity index 50% rename from Tests/APIRoute.swift rename to Tests/TestRepository.swift index 9b20e4a4..784f7e20 100644 --- a/Tests/APIRoute.swift +++ b/Tests/TestRepository.swift @@ -1,6 +1,6 @@ // Queue.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -22,8 +22,8 @@ import TermiNetwork // swiftlint:disable function_body_length cyclomatic_complexity -enum APIRoute: RouteProtocol { - // Define your routes +enum TestRepository: EndpointProtocol { + // Define your endpoints case testHeaders case testOverrideHeaders case testGetParams(value1: Bool, value2: Int, value3: Double, value4: String, value5: String?) @@ -48,121 +48,107 @@ enum APIRoute: RouteProtocol { return configuration } - // Set method, path, params, headers for each route - func configure() -> RouteConfiguration { + // Set method, path, params, headers for each endpoint + func configure() -> EndpointConfiguration { switch self { case .testHeaders: - return RouteConfiguration( + return .init( method: .get, path: .path(["test_headers"]), headers: ["Authorization": "XKJajkBXAUIbakbxjkasbxjkas", "Custom-Header": "test!!!!"], - mockFilePath: .path(["main-router", "headers.json"]) + mockFilePath: .path(["main-repo", "headers.json"]) ) case .testOverrideHeaders: - return RouteConfiguration( + return .init( method: .get, path: .path(["test_headers"]), headers: ["Authorization": "0", "Custom-Header": "0", "User-Agent": "ios"], - mockFilePath: .path(["main-router", "invalid.json"]) + mockFilePath: .path(["main-repo", "invalid.json"]) ) case let .testGetParams(value1, value2, value3, value4, value5): - return RouteConfiguration( - method: .get, - path: .path(["test_params"]), - params: ["key1": value1, "key2": value2, "key3": value3, "key4": value4, "key5": value5] + return .init(method: .get, + path: .path(["test_params"]), + params: ["key1": value1, "key2": value2, "key3": value3, "key4": value4, "key5": value5] ) case let .testPostParamsxWWWFormURLEncoded(value1, value2, value3, value4, value5): - return RouteConfiguration( - method: .post, - path: .path(["test_params"]), - params: ["key1": value1, "key2": value2, "key3": value3, "key4": value4, "key5": value5], - configuration: Configuration(requestBodyType: .xWWWFormURLEncoded) + return .init(method: .post, + path: .path(["test_params"]), + params: ["key1": value1, "key2": value2, "key3": value3, "key4": value4, "key5": value5], + configuration: Configuration(requestBodyType: .xWWWFormURLEncoded) ) case .testConfiguration: - return RouteConfiguration( - method: .post, - path: .path(["test_params"]), - configuration: Configuration(cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, - timeoutInterval: 12, - requestBodyType: .JSON) + return .init(method: .post, + path: .path(["test_params"]), + configuration: Configuration(cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, + timeoutInterval: 12, + requestBodyType: .JSON) ) case .testConfigurationParameterized(let conf): - return RouteConfiguration(method: .get, - path: .path(["a"]), - params: nil, - headers: nil, - configuration: conf) + return .init(method: .get, + path: .path(["a"]), + params: nil, + headers: nil, + configuration: conf) case let .testPostParams(value1, value2, value3, value4, value5): - return RouteConfiguration( - method: .post, - path: .path(["test_params"]), - params: ["key1": value1, "key2": value2, "key3": value3, "key4": value4, "key5": value5], - configuration: Configuration(requestBodyType: .JSON) + return .init(method: .post, + path: .path(["test_params"]), + params: ["key1": value1, "key2": value2, "key3": value3, "key4": value4, "key5": value5], + configuration: Configuration(requestBodyType: .JSON) ) case let .testInvalidParams(value1, value2): - return RouteConfiguration( - method: .get, - path: .path(["test_params"]), - params: ["fff": value1, "aaa": value2] + return .init(method: .get, + path: .path(["test_params"]), + params: ["fff": value1, "aaa": value2] ) case .testStatusCode(let code): - return RouteConfiguration( - method: .get, - path: .path(["test_status_code"]), - params: ["status_code": code] + return .init(method: .get, + path: .path(["test_status_code"]), + params: ["status_code": code] ) case .testEmptyBody: - return RouteConfiguration( - method: .get, - path: .path(["test_empty_response"]) + return .init(method: .get, + path: .path(["test_empty_response"]) ) case .testImage(let imageName): - return RouteConfiguration( - method: .get, - path: .path([imageName]) + return .init(method: .get, + path: .path([imageName]) ) case .testPinning(let certPath): - return RouteConfiguration( - method: .get, - path: .path(["test_empty_response"]), - configuration: testPinningConfiguration(withCertPaths: [certPath]) + return .init(method: .get, + path: .path(["test_empty_response"]), + configuration: testPinningConfiguration(withCertPaths: [certPath]) ) case .testEncryptParams(let value): - return RouteConfiguration( - method: .post, - path: .path(["test_encrypt_params"]), - params: ["value": value] + return .init(method: .post, + path: .path(["test_encrypt_params"]), + params: ["value": value] ) case .dataUpload(let data, let param): - return RouteConfiguration( - method: .post, - path: .path(["file_upload"]), - params: ["file": MultipartFormDataPartType.data(data: data, - filename: "test.jpg", - contentType: "image/jpeg"), - "test_param": MultipartFormDataPartType.value(value: param)] + return .init(method: .post, + path: .path(["file_upload"]), + params: ["file": MultipartFormDataPartType.data(data: data, + filename: "test.jpg", + contentType: "image/jpeg"), + "test_param": MultipartFormDataPartType.value(value: param)] ) case .fileUpload(let url, let param): - return RouteConfiguration( - method: .post, - path: .path(["file_upload"]), - params: ["file": MultipartFormDataPartType.url(url), - "test_param": MultipartFormDataPartType.value(value: param)] + return .init(method: .post, + path: .path(["file_upload"]), + params: ["file": MultipartFormDataPartType.url(url), + "test_param": MultipartFormDataPartType.value(value: param)] ) case .fileDownload: - return RouteConfiguration(method: .get, - path: .path(["downloads", "3cwHqdwsRyuX"])) + return EndpointConfiguration(method: .get, + path: .path(["downloads", "3cwHqdwsRyuX"])) case .fileUploadWithStatusCode(let url, let param, let status): - return RouteConfiguration( - method: .post, - path: .path(["file_upload"]), - params: ["file": MultipartFormDataPartType.url(url), - "test_param": MultipartFormDataPartType.value(value: param), - "status": status] + return .init(method: .post, + path: .path(["file_upload"]), + params: ["file": MultipartFormDataPartType.url(url), + "test_param": MultipartFormDataPartType.value(value: param), + "status": status] ) - } } } diff --git a/Tests/TestRequest.swift b/Tests/TestRequest.swift index 7020ea8e..6c501dc0 100644 --- a/Tests/TestRequest.swift +++ b/Tests/TestRequest.swift @@ -1,6 +1,6 @@ // TestRequest.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -22,24 +22,22 @@ import XCTest import TermiNetwork class TestRequest: XCTestCase { - lazy var router: Router = { - return Router(configuration: Configuration(verbose: true)) + lazy var client: Client = { + return .init(configuration: Configuration(verbose: true)) }() - lazy var router2: Router = { - return Router(environment: Env.google) + lazy var client2: Client = { + return .init(environment: Env.google) }() - lazy var routerWithMiddleware: Router = { + lazy var clientWithMiddleware: Client = { let configuration = Configuration() configuration.requestMiddleware = [CryptoMiddleware.self] configuration.verbose = true configuration.requestBodyType = .JSON - let router = Router(environment: Env.termiNetworkRemote, - configuration: configuration) - - return router + return Client(environment: Env.termiNetworkRemote, + configuration: configuration) }() override func setUp() { @@ -57,7 +55,7 @@ class TestRequest: XCTestCase { let expectation = XCTestExpectation(description: "testHeaders") var failed = true - router.request(for: .testHeaders) + client.request(for: .testHeaders) .success(responseType: TestHeaders.self) { object in failed = !(object.authorization == "XKJajkBXAUIbakbxjkasbxjkas" && object.customHeader == "test!!!!") expectation.fulfill() @@ -75,7 +73,7 @@ class TestRequest: XCTestCase { let expectation = XCTestExpectation(description: "testOverrideHeaders") var failed = true - router.request(for: .testOverrideHeaders) + client.request(for: .testOverrideHeaders) .success(responseType: TestHeaders.self) { object in failed = !(object.authorization == "0" && object.customHeader == "0" && @@ -95,7 +93,7 @@ class TestRequest: XCTestCase { let expectation = XCTestExpectation(description: "testGetParams") var failed = true - router.request(for: .testGetParams(value1: true, + client.request(for: .testGetParams(value1: true, value2: 3, value3: 5.13453124189, value4: "test", @@ -122,7 +120,7 @@ class TestRequest: XCTestCase { let expectation = XCTestExpectation(description: "testGetParamsEscaped") var failed = true - router.request(for: .testGetParams(value1: true, + client.request(for: .testGetParams(value1: true, value2: 3, value3: 5.13453124189, value4: "τεστ", @@ -149,7 +147,7 @@ class TestRequest: XCTestCase { let expectation = XCTestExpectation(description: "testPostParams") var failed = true - router.request(for: .testPostParamsxWWWFormURLEncoded(value1: true, + client.request(for: .testPostParamsxWWWFormURLEncoded(value1: true, value2: 3, value3: 5.13453124189, value4: "test", @@ -175,7 +173,7 @@ class TestRequest: XCTestCase { let expectation = XCTestExpectation(description: "testJSONRequestPostParams") var failed = true - router.request(for: .testPostParams(value1: true, + client.request(for: .testPostParams(value1: true, value2: 3, value3: 5.13453124189, value4: "test", @@ -269,11 +267,11 @@ class TestRequest: XCTestCase { var failed = true Queue.shared.cancelAllOperations() - let request = Request(route: APIRoute.testPostParams(value1: true, - value2: 3, - value3: 5.13453124189, - value4: "test", - value5: nil)) + let request = Request(endpoint: TestRepository.testPostParams(value1: true, + value2: 3, + value3: 5.13453124189, + value4: "test", + value5: nil)) request.configuration.requestBodyType = .JSON request.configuration.verbose = true request.success(responseType: String.self) { _ in @@ -286,21 +284,21 @@ class TestRequest: XCTestCase { } func testConfiguration() { - var request = Request(route: APIRoute.testInvalidParams(value1: "a", value2: "b")) + var request = Request(endpoint: TestRepository.testInvalidParams(value1: "a", value2: "b")) var urlRequest = try? request.asRequest() XCTAssert(urlRequest?.timeoutInterval == 60) XCTAssert(request.configuration.cachePolicy == .useProtocolCachePolicy) XCTAssert(request.configuration.requestBodyType == .xWWWFormURLEncoded) Environment.set(Env.termiNetworkLocal) - request = Request(route: APIRoute.testHeaders) + request = Request(endpoint: TestRepository.testHeaders) urlRequest = try? request.asRequest() XCTAssert(urlRequest?.timeoutInterval == 32) XCTAssert(request.configuration.cachePolicy == .returnCacheDataElseLoad) XCTAssert(request.configuration.requestBodyType == .JSON) Environment.set(Env.termiNetworkRemote) - request = Request(route: APIRoute.testConfiguration) + request = Request(endpoint: TestRepository.testConfiguration) urlRequest = try? request.asRequest() XCTAssert(urlRequest?.timeoutInterval == 12) XCTAssert(request.configuration.cachePolicy == .reloadIgnoringLocalAndRemoteCacheData) @@ -315,7 +313,7 @@ class TestRequest: XCTestCase { var failed = true - router.request(for: .testGetParams(value1: false, + client.request(for: .testGetParams(value1: false, value2: 2, value3: 3, value4: "1", @@ -335,7 +333,7 @@ class TestRequest: XCTestCase { failed = true - router2.request(for: .testGetParams(value1: false, + client2.request(for: .testGetParams(value1: false, value2: 2, value3: 3, value4: "1", @@ -359,7 +357,7 @@ class TestRequest: XCTestCase { let expectation = XCTestExpectation(description: "testMiddleware") - routerWithMiddleware.request(for: .testEncryptParams(value: "Hola!!!")) + clientWithMiddleware.request(for: .testEncryptParams(value: "Hola!!!")) .success(responseType: EncryptedModel.self) { model in failed = model.value != "Hola!!!" expectation.fulfill() @@ -379,11 +377,11 @@ class TestRequest: XCTestCase { fileprivate func sampleRequest(queue: Queue? = Queue.shared, onSuccess: SuccessCallback? = nil) { - let call = Request(route: APIRoute.testPostParams(value1: true, - value2: 3, - value3: 5.13453124189, - value4: "test", - value5: nil)) + let call = Request(endpoint: TestRepository.testPostParams(value1: true, + value2: 3, + value3: 5.13453124189, + value4: "test", + value5: nil)) call.configuration.requestBodyType = .JSON call.queue(queue ?? Queue.shared) .success(responseType: TestJSONParams.self) { object in @@ -396,7 +394,7 @@ class TestRequest: XCTestCase { let expectation = XCTestExpectation(description: "testResponseHeaders") - routerWithMiddleware.request(for: .testEncryptParams(value: "Hola!!!")) + clientWithMiddleware.request(for: .testEncryptParams(value: "Hola!!!")) .success(responseType: Data.self, responseHandler: { _ in }) .responseHeaders { (headers, _) in failed = headers?["Content-Type"] != "application/json; charset=utf-8" diff --git a/Tests/TestRequestAsync.swift b/Tests/TestRequestAsync.swift index 1be83805..9d1b8274 100644 --- a/Tests/TestRequestAsync.swift +++ b/Tests/TestRequestAsync.swift @@ -1,6 +1,6 @@ // TestRequest.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -21,25 +21,8 @@ import XCTest import TermiNetwork class TestRequestAsync: XCTestCase { - lazy var router: Router = { - return Router(configuration: Configuration(verbose: true)) - }() - - lazy var router2: Router = { - return Router(environment: Env.google) - }() - - lazy var routerWithMiddleware: Router = { - let configuration = Configuration() - configuration.requestMiddleware = [CryptoMiddleware.self] - configuration.verbose = true - configuration.requestBodyType = .JSON - - let router = Router(environment: Env.termiNetworkRemote, - configuration: configuration) - - return router - }() + lazy var client: Client = .init(configuration: Configuration(verbose: true)) + lazy var client2: Client = .init(environment: Env.google) override func setUp() { super.setUp() @@ -55,7 +38,7 @@ class TestRequestAsync: XCTestCase { func testHeaders() async { var failed = true do { - let response: TestHeaders = try await router.request(for: .testHeaders).async() + let response: TestHeaders = try await client.request(for: .testHeaders).async() failed = !(response.authorization == "XKJajkBXAUIbakbxjkasbxjkas" && response.customHeader == "test!!!!") } catch { } @@ -143,7 +126,7 @@ class TestRequestAsync: XCTestCase { } func testGetParamsWithTransformerSuccess() async { - let testModel = try? await router.request( + let testModel = try? await client.request( for: .testGetParams(value1: true, value2: 3, value3: 5.13453124189, @@ -161,7 +144,7 @@ class TestRequestAsync: XCTestCase { var failed = true do { - try await router.request( + try await client.request( for: .testGetParams(value1: true, value2: 3, value3: 5.13453124189, @@ -190,7 +173,7 @@ class TestRequestAsync: XCTestCase { func testGetParamsWithTransformerSuccessTransformError() async { var failed = true - let req = router.request( + let req = client.request( for: .testGetParams(value1: true, value2: 3, value3: 5.13453124189, @@ -211,7 +194,7 @@ class TestRequestAsync: XCTestCase { } func testResponseValidImageData() async { - let image = try? await router.request(for: .testImage(imageName: "sample.jpeg")).async(as: UIImage.self) + let image = try? await client.request(for: .testImage(imageName: "sample.jpeg")).async(as: UIImage.self) XCTAssertNotNil(image) } diff --git a/Tests/TestTNErrors.swift b/Tests/TestTNErrors.swift index 8fe95286..b6deeb99 100644 --- a/Tests/TestTNErrors.swift +++ b/Tests/TestTNErrors.swift @@ -1,6 +1,6 @@ // TestTNErrors.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -22,9 +22,7 @@ import XCTest import TermiNetwork class TestTNErrors: XCTestCase { - var router: Router { - return Router() - } + lazy var client: Client = .init() override func setUp() { super.setUp() @@ -52,7 +50,7 @@ class TestTNErrors: XCTestCase { expectation.fulfill() } .failure { error in - if case TNError.environmenotSet = error { + if case TNError.environmentNotSet = error { failed = true } else { failed = false @@ -65,12 +63,12 @@ class TestTNErrors: XCTestCase { XCTAssert(!failed) } - func testEnvironmenotSetWithRoute() { + func testDidNotSetEnvironmentWithEndpoint() { Environment.current = nil - let expectation = XCTestExpectation(description: "testEnvironmenotSetWithRoute") + let expectation = XCTestExpectation(description: "testDidNotSetEnvironmentWithEndpoint") var failed = true - router.request(for: .testPostParams(value1: true, + client.request(for: .testPostParams(value1: true, value2: 1, value3: 2, value4: "Dsa", @@ -80,7 +78,7 @@ class TestTNErrors: XCTestCase { expectation.fulfill() } .failure { error in - if case TNError.environmenotSet = error { + if case TNError.environmentNotSet = error { failed = false } expectation.fulfill() @@ -115,7 +113,7 @@ class TestTNErrors: XCTestCase { let expectation = XCTestExpectation(description: "testResponseDataIsNotEmpty") var failed = true - router.request(for: .testEmptyBody) + client.request(for: .testEmptyBody) .success(responseType: Data.self) { _ in expectation.fulfill() failed = false @@ -134,7 +132,7 @@ class TestTNErrors: XCTestCase { let expectation = XCTestExpectation(description: "testResponseInvalidImageData") var failed = true - router.request(for: .testPostParams(value1: false, + client.request(for: .testPostParams(value1: false, value2: 1, value3: 2, value4: "", @@ -162,7 +160,7 @@ class TestTNErrors: XCTestCase { let expectation = XCTestExpectation(description: "testResponseValidImageData") var failed = true - router.request(for: .testImage(imageName: "sample.jpeg")) + client.request(for: .testImage(imageName: "sample.jpeg")) .success(responseType: UIImage.self) { _ in expectation.fulfill() failed = false @@ -181,7 +179,7 @@ class TestTNErrors: XCTestCase { let expectation = XCTestExpectation(description: "testResponseCannotDeserialize") var failed = true - router.request(for: .testInvalidParams(value1: "a", value2: "b")) + client.request(for: .testInvalidParams(value1: "a", value2: "b")) .success(responseType: TestParams.self) { _ in failed = true expectation.fulfill() @@ -207,7 +205,7 @@ class TestTNErrors: XCTestCase { let expectation = XCTestExpectation(description: "testResponseCanDeserialize") var failed = true - router.request(for: .testGetParams(value1: false, + client.request(for: .testGetParams(value1: false, value2: 3, value3: 1.32, value4: "Test", @@ -232,7 +230,7 @@ class TestTNErrors: XCTestCase { let expectation = XCTestExpectation(description: "tesetworkError") var failed = true - let req = router.request(for: .testInvalidParams(value1: "a", value2: "b")) + let req = client.request(for: .testInvalidParams(value1: "a", value2: "b")) req.configuration.interceptors = [] req.success(responseType: Data.self) { _ in @@ -260,7 +258,7 @@ class TestTNErrors: XCTestCase { let expectation = XCTestExpectation(description: "tesotSuccess") var failed = true - router.request(for: .testStatusCode(code: 404)) + client.request(for: .testStatusCode(code: 404)) .success(responseType: String.self) { _ in expectation.fulfill() failed = true @@ -271,11 +269,10 @@ class TestTNErrors: XCTestCase { failed = code != 404 default: failed = true + } + expectation.fulfill() } - expectation.fulfill() - } - wait(for: [expectation], timeout: 60) XCTAssert(!failed) @@ -285,7 +282,7 @@ class TestTNErrors: XCTestCase { let expectation = XCTestExpectation(description: "testCancelled") var failed = true - let request = Request(route: APIRoute.testStatusCode(code: 404)) + let request = Request(endpoint: TestRepository.testStatusCode(code: 404)) request.success(responseType: Data.self) { _ in expectation.fulfill() } @@ -310,7 +307,7 @@ class TestTNErrors: XCTestCase { let expectation = XCTestExpectation(description: "testErrorCannotDeserialize") var failed = true - let request = Request(route: APIRoute.testStatusCode(code: 404)) + let request = Request(endpoint: TestRepository.testStatusCode(code: 404)) request.success(responseType: TestParams.self) { _ in expectation.fulfill() } @@ -333,11 +330,11 @@ class TestTNErrors: XCTestCase { let expectation = XCTestExpectation(description: "testErrorCannotDeserialize") var failed = true - let request = Request(route: APIRoute.testGetParams(value1: false, - value2: 3, - value3: 1.32, - value4: "Test", - value5: nil)) + let request = Request(endpoint: TestRepository.testGetParams(value1: false, + value2: 3, + value3: 1.32, + value4: "Test", + value5: nil)) request.success(responseType: EncryptedModel.self) { _ in expectation.fulfill() } @@ -360,7 +357,7 @@ class TestTNErrors: XCTestCase { let expectation = XCTestExpectation(description: "testErrorCannotDeserialize") var failed = true - let request = Request(route: APIRoute.testStatusCode(code: 401)) + let request = Request(endpoint: TestRepository.testStatusCode(code: 401)) request.configuration.keyDecodingStrategy = .convertFromSnakeCase request.success(responseType: EncryptedModel.self) { _ in expectation.fulfill() @@ -384,7 +381,7 @@ class TestTNErrors: XCTestCase { let expectation = XCTestExpectation(description: "testErrorCannotDeserialize") var failed = true - let request = Request(route: APIRoute.testStatusCode(code: 401)) + let request = Request(endpoint: TestRepository.testStatusCode(code: 401)) request.configuration.keyDecodingStrategy = .convertFromSnakeCase request.success(responseType: EncryptedModel.self) { _ in expectation.fulfill() diff --git a/Tests/TestTransformer.swift b/Tests/TestTransformer.swift index 1b7c5ce4..78fc29ae 100644 --- a/Tests/TestTransformer.swift +++ b/Tests/TestTransformer.swift @@ -1,6 +1,6 @@ // TestTransformer.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 diff --git a/Tests/TestTransformers.swift b/Tests/TestTransformers.swift index 655da2aa..94372aac 100644 --- a/Tests/TestTransformers.swift +++ b/Tests/TestTransformers.swift @@ -1,6 +1,6 @@ // TestTransformers.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -21,9 +21,7 @@ import XCTest import TermiNetwork class TestTransformers: XCTestCase { - lazy var router: Router = { - return Router(configuration: Configuration(verbose: true)) - }() + lazy var client: Client = .init(configuration: Configuration(verbose: true)) override class func setUp() { Environment.set(Env.termiNetworkRemote) @@ -49,7 +47,7 @@ class TestTransformers: XCTestCase { let expectation = XCTestExpectation(description: "testGetParamsWithTransformerSuccess") var failed = true var testModel: TestModel? - router.request(for: .testGetParams(value1: true, + client.request(for: .testGetParams(value1: true, value2: 3, value3: 5.13453124189, value4: "test", @@ -72,7 +70,7 @@ class TestTransformers: XCTestCase { let expectation = XCTestExpectation(description: "testGetParamsWithTransformerSuccessCannotDeserialize") var failed = true - let req = router.request(for: .testGetParams(value1: true, + let req = client.request(for: .testGetParams(value1: true, value2: 3, value3: 5.13453124189, value4: "test", @@ -99,7 +97,7 @@ class TestTransformers: XCTestCase { let expectation = XCTestExpectation(description: "testGetParamsWithTransformerSuccessTransformError") var failed = true - let req = router.request(for: .testGetParams(value1: true, + let req = client.request(for: .testGetParams(value1: true, value2: 3, value3: 5.13453124189, value4: "test", @@ -126,7 +124,7 @@ class TestTransformers: XCTestCase { let expectation = XCTestExpectation(description: "testGetParamsWithTransformer") var failed = true - let req = router.request(for: .testGetParams(value1: true, + let req = client.request(for: .testGetParams(value1: true, value2: 3, value3: 5.13453124189, value4: "test", diff --git a/Tests/TestUploadOperations.swift b/Tests/TestUploadOperations.swift index 1f87886e..c0699964 100644 --- a/Tests/TestUploadOperations.swift +++ b/Tests/TestUploadOperations.swift @@ -1,6 +1,6 @@ // TestUploadOperations.swift // -// Copyright © 2018-2022 Vassilis Panagiotopoulos. All rights reserved. +// Copyright © 2018-2023 Vassilis Panagiotopoulos. All rights reserved. // // 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 @@ -26,9 +26,9 @@ class TestUploadOperations: XCTestCase { verbose: true) }() - lazy var router: Router = { - return Router(environment: Env.termiNetworkRemote, - configuration: configuration) + lazy var client: Client = { + return .init(environment: Env.termiNetworkRemote, + configuration: configuration) }() override func setUp() { @@ -55,7 +55,7 @@ class TestUploadOperations: XCTestCase { let checksum = TestHelpers.sha256(url: URL(fileURLWithPath: filePath)) - router.request(for: .dataUpload(data: uploadData, param: "bhbbrbrbrhbh")) + client.request(for: .dataUpload(data: uploadData, param: "bhbbrbrbrhbh")) .upload(responseType: FileResponse.self, progressUpdate: { bytesSent, totalBytes, progress in completed = bytesSent == totalBytes && progress == 1 @@ -89,7 +89,7 @@ class TestUploadOperations: XCTestCase { let checksum = TestHelpers.sha256(url: URL(fileURLWithPath: filePath)) - router.request(for: .dataUpload(data: uploadData, param: "bhbbrbrbrhbh")) + client.request(for: .dataUpload(data: uploadData, param: "bhbbrbrbrhbh")) .upload(transformer: TestUploadTransformer.self, progressUpdate: { bytesSent, totalBytes, progress in completed = bytesSent == totalBytes && progress == 1 @@ -125,7 +125,7 @@ class TestUploadOperations: XCTestCase { queue.maxConcurrentOperationCount = 1 for _ in 0.. = { - return Router(environment: Env.termiNetworkRemote, - configuration: configuration) + lazy var client: Client = { + return .init(environment: Env.termiNetworkRemote, + configuration: configuration) }() override func setUp() { @@ -56,7 +56,7 @@ class TestUploadOperationsAsync: XCTestCase { let checksum = TestHelpers.sha256(url: URL(fileURLWithPath: filePath)) do { - let response = try await router.request(for: .dataUpload(data: uploadData, param: "bhbbrbrbrhbh")) + let response = try await client.request(for: .dataUpload(data: uploadData, param: "bhbbrbrbrhbh")) .asyncUpload( as: FileResponse.self, progressUpdate: { bytesSent, totalBytes, progress in @@ -86,7 +86,7 @@ class TestUploadOperationsAsync: XCTestCase { } do { - try await router.request(for: .dataUpload(data: uploadData, param: "bhbbrbrbrhbh")) + try await client.request(for: .dataUpload(data: uploadData, param: "bhbbrbrbrhbh")) .asyncUpload( as: FileResponse.self, progressUpdate: nil) @@ -123,7 +123,7 @@ class TestUploadOperationsAsync: XCTestCase { let checksum = TestHelpers.sha256(url: URL(fileURLWithPath: filePath)) do { - let response = try await router.request(for: .dataUpload(data: uploadData, param: "bhbbrbrbrhbh")) + let response = try await client.request(for: .dataUpload(data: uploadData, param: "bhbbrbrbrhbh")) .asyncUpload(using: TestUploadTransformer.self, progressUpdate: { bytesSent, totalBytes, progress in completed = bytesSent == totalBytes && progress == 1 @@ -151,7 +151,7 @@ class TestUploadOperationsAsync: XCTestCase { } do { - try await router.request(for: .dataUpload(data: uploadData, param: "bhbbrbrbrhbh")) + try await client.request(for: .dataUpload(data: uploadData, param: "bhbbrbrbrhbh")) .asyncUpload(using: TestUploadTransformer.self, progressUpdate: nil) @@ -191,7 +191,7 @@ class TestUploadOperationsAsync: XCTestCase { for _ in 0..4I&H?=8kQ zEt`@_IN&Zm6<}9Yi>?0;;f(uFu103V!WCeGrEH+rj^@aLPVLDrAu3NGEJBA|b>eY0 zHTTg*7XFtGU^C7nhGU+;T+Ic#UQt@*1{-pi5z*hyN>#wdI)VNX?5Grsx;$YC(tdw^ zne{*})E!cHeu#Q%BYX0(wV)QtX3jptte!eNl^W}*ylaA=bM=Y#BrQYNcfL1ClmLoE z8SXq)6Ey+d&rvHXlMk5yHcG?_8jptgXsA8te5lFK@DcXtyJnL zJ~ycq2Ujpaej33IR}ax_>+>lLP67{)5ds4N00EVY?hvk z&d{u@2VIK|+R!w!C;|one**>zD+U1s0oHi}1Ofzs^aO$N0Pg^G0JlE-B;TA(x^?n7 z#kyGZY+d|9&w8IV#GV}qfhFy0w5@hd+~{*Gtg5h3+G-s zkyieuPte|MhY>One|4lwQ)|>P4F(A+hDe6@4FLfQ1potr0RaFR;b!beA%$x0XaR!O z82{6ZnmcGg$xu5Gf$8~9vF|3A`h~z*LU-;y?4k&P&6vl`hUWfk#vbzXQ1pEV+djN% zZ~u=`srwL0rFABvvUHqUepRfziA_eB#cA;gn#?*TOdR}ve{{IxvfGmv#-HIn$>p_t zEtj7m;hBJy>tT9;5LikXg;ldKe|@en58u+*i?9(_+uS!CSCj(yJO$#` o^a0w+B}9O49JJ9$FAPQ<`;Yb4FW0qWC3XPTgf*p}J4PBC=NIOYuK)l5 delta 915 zcmV;E18n@p3daf|FoFd`FoFatpaTK{0s;~QNNXPJGpv#C{Mh4M?}M0 zCdj|#Z^O>p|6&0TJ!r1$+d0MpAYHghi4@>h2qOCgIyNQ<_z~#7e{w_sZ^d}gt*DIK zXvqL~0O&r@+CKFLH8ST{D7=Yl$ph2N(GhFx>uKS4eQgH4ZU6uQgn%Z2^Z)<^0{}=c zMgk!K$&D4IQt$dUfF4zPKlkr^3AYA{LXZ}JC1 z7zN0^S05zVAFfnxFQ>5(oL3K=kVm5yVZ3Z5A(>V?cvS?5|Gm-7@hjOjS8*JW zXC38qWT&)Sk{eBW41?GZL5LIS2ijk_VIf1L2sIg4$d_f(j_EI*D2MIkDptAF#r<$S z`yEefdxIl6b|pw~|8CQdpRsVVRPq!g03qLklJx1