From 24f3526f4421ff338ccbde60e7abb00fa60a3650 Mon Sep 17 00:00:00 2001 From: Iqbal Nur Haq Binkidi <34118228+iqbalnurhaq@users.noreply.github.com> Date: Fri, 6 Jan 2023 09:18:01 +0700 Subject: [PATCH 1/2] Initial commit --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8355bcd --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 CeXup + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From b30b131d5bcf72002821cb484acd8895eebee8c5 Mon Sep 17 00:00:00 2001 From: Iqbal Nur Haq Date: Wed, 11 Jan 2023 09:03:59 +0700 Subject: [PATCH 2/2] Delete Readme --- .gitignore | 9 ++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++ Package.swift | 33 +++++++++++++ README.md | 1 - Sources/Core/Data/DataSource.swift | 16 +++++++ Sources/Core/Data/LocaleDataSource.swift | 20 ++++++++ Sources/Core/Data/Repository/Repository.swift | 16 +++++++ Sources/Core/Domain/UseCase/Interactor.swift | 23 +++++++++ Sources/Core/Domain/UseCase/UseCase.swift | 16 +++++++ Sources/Core/Extension/CustomError+Ext.swift | 36 ++++++++++++++ Sources/Core/Extension/Result+Ext.swift | 22 +++++++++ Sources/Core/Mapper.swift | 18 +++++++ Sources/Core/Presentation/Presenter.swift | 48 +++++++++++++++++++ Sources/Core/Utils/Prefs.swift | 32 +++++++++++++ Tests/CoreTests/CoreTests.swift | 11 +++++ 15 files changed, 308 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 .swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Package.swift delete mode 100644 README.md create mode 100644 Sources/Core/Data/DataSource.swift create mode 100644 Sources/Core/Data/LocaleDataSource.swift create mode 100644 Sources/Core/Data/Repository/Repository.swift create mode 100644 Sources/Core/Domain/UseCase/Interactor.swift create mode 100644 Sources/Core/Domain/UseCase/UseCase.swift create mode 100644 Sources/Core/Extension/CustomError+Ext.swift create mode 100644 Sources/Core/Extension/Result+Ext.swift create mode 100644 Sources/Core/Mapper.swift create mode 100644 Sources/Core/Presentation/Presenter.swift create mode 100644 Sources/Core/Utils/Prefs.swift create mode 100644 Tests/CoreTests/CoreTests.swift diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3b29812 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +/.build +/Packages +/*.xcodeproj +xcuserdata/ +DerivedData/ +.swiftpm/config/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..19da92a --- /dev/null +++ b/Package.swift @@ -0,0 +1,33 @@ +// swift-tools-version: 5.7 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "Core", + platforms: [.iOS(.v15), .macOS(.v10_15)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "Core", + targets: ["Core"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + .package(name: "Realm", url: "https://github.com/realm/realm-cocoa.git", from: "10.5.2") + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "Core", + dependencies: [ + .product(name: "RealmSwift", package: "Realm"), + ] + ), + .testTarget( + name: "CoreTests", + dependencies: ["Core"]), + ] +) diff --git a/README.md b/README.md deleted file mode 100644 index e87b74d..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -IOS Module Core diff --git a/Sources/Core/Data/DataSource.swift b/Sources/Core/Data/DataSource.swift new file mode 100644 index 0000000..2ef8e21 --- /dev/null +++ b/Sources/Core/Data/DataSource.swift @@ -0,0 +1,16 @@ +// +// File.swift +// +// +// Created by Iqbal Nur Haq on 03/01/23. +// + +import Foundation +import Combine + +public protocol DataSource { + associatedtype Request + associatedtype Response + + func execute(request: Request?) -> AnyPublisher +} diff --git a/Sources/Core/Data/LocaleDataSource.swift b/Sources/Core/Data/LocaleDataSource.swift new file mode 100644 index 0000000..c82a76c --- /dev/null +++ b/Sources/Core/Data/LocaleDataSource.swift @@ -0,0 +1,20 @@ +// +// File.swift +// +// +// Created by Iqbal Nur Haq on 03/01/23. +// + +import Foundation +import Combine + +public protocol LocaleDataSource { + associatedtype Request + associatedtype Response + + func list(request: Request?) -> AnyPublisher<[Response], Error> + func add(entities: [Response]) -> AnyPublisher + func addOne(entity: Response) -> AnyPublisher + func get(id: String?) -> AnyPublisher + func update(id: Int, entity: Response) -> AnyPublisher +} diff --git a/Sources/Core/Data/Repository/Repository.swift b/Sources/Core/Data/Repository/Repository.swift new file mode 100644 index 0000000..01a46c3 --- /dev/null +++ b/Sources/Core/Data/Repository/Repository.swift @@ -0,0 +1,16 @@ +// +// File.swift +// +// +// Created by Iqbal Nur Haq on 03/01/23. +// + +import Foundation +import Combine + +public protocol Repository { + associatedtype Request + associatedtype Response + + func execute(request: Request?) -> AnyPublisher +} diff --git a/Sources/Core/Domain/UseCase/Interactor.swift b/Sources/Core/Domain/UseCase/Interactor.swift new file mode 100644 index 0000000..0c99c46 --- /dev/null +++ b/Sources/Core/Domain/UseCase/Interactor.swift @@ -0,0 +1,23 @@ +// +// File.swift +// +// +// Created by Iqbal Nur Haq on 03/01/23. +// + +import Foundation +import Combine + +public struct Interactor: UseCase +where R.Request == Request, R.Response == Response { + + private let _repository: R + + public init(repository: R) { + _repository = repository + } + + public func execute(request: Request?) -> AnyPublisher { + _repository.execute(request: request) + } +} diff --git a/Sources/Core/Domain/UseCase/UseCase.swift b/Sources/Core/Domain/UseCase/UseCase.swift new file mode 100644 index 0000000..31c29d2 --- /dev/null +++ b/Sources/Core/Domain/UseCase/UseCase.swift @@ -0,0 +1,16 @@ +// +// File.swift +// +// +// Created by Iqbal Nur Haq on 03/01/23. +// + +import Foundation +import Combine + +public protocol UseCase { + associatedtype Request + associatedtype Response + + func execute(request: Request?) -> AnyPublisher +} diff --git a/Sources/Core/Extension/CustomError+Ext.swift b/Sources/Core/Extension/CustomError+Ext.swift new file mode 100644 index 0000000..c0adb4f --- /dev/null +++ b/Sources/Core/Extension/CustomError+Ext.swift @@ -0,0 +1,36 @@ +// +// File.swift +// +// +// Created by Iqbal Nur Haq on 03/01/23. +// + +import Foundation + +public enum URLError: LocalizedError { + case invalidRequest + case invalidResponse + case addressUnreachable(URL) + case custom(String) + + public var errorDescription: String? { + switch self { + case .invalidRequest: return "Request is null." + case .invalidResponse: return "The server responded with garbage." + case .addressUnreachable(let url): return "\(url.absoluteString) is unreachable." + case .custom(let message): return "\(message)" + } + } +} + +public enum DataBaseError: LocalizedError { + case invalidInstance + case requestFailed + + public var errorDescription: String? { + switch self { + case .invalidInstance: return "Database can't instance." + case .requestFailed: return "Your request failed." + } + } +} diff --git a/Sources/Core/Extension/Result+Ext.swift b/Sources/Core/Extension/Result+Ext.swift new file mode 100644 index 0000000..a95cd61 --- /dev/null +++ b/Sources/Core/Extension/Result+Ext.swift @@ -0,0 +1,22 @@ +// +// File.swift +// +// +// Created by Iqbal Nur Haq on 03/01/23. +// + +import Foundation +import RealmSwift + +extension Results { + public func toArray(ofType: T.Type) -> [T] { + var array = [T]() + for index in 0 ..< count { + if let result = self[index] as? T { + array.append(result) + } + } + + return array + } +} diff --git a/Sources/Core/Mapper.swift b/Sources/Core/Mapper.swift new file mode 100644 index 0000000..238743e --- /dev/null +++ b/Sources/Core/Mapper.swift @@ -0,0 +1,18 @@ +// +// File.swift +// +// +// Created by Iqbal Nur Haq on 04/01/23. +// + +import Foundation + +public protocol Mapper { + associatedtype Request + associatedtype Response + associatedtype Entity + associatedtype Domain + + func transformResponseToEntity(request: Request?, response: Response) -> Entity + func transformEntityToDomain(entity: Entity) -> Domain +} diff --git a/Sources/Core/Presentation/Presenter.swift b/Sources/Core/Presentation/Presenter.swift new file mode 100644 index 0000000..5e8f85c --- /dev/null +++ b/Sources/Core/Presentation/Presenter.swift @@ -0,0 +1,48 @@ +// +// File.swift +// +// +// Created by Iqbal Nur Haq on 05/01/23. +// + +import Foundation +import SwiftUI +import Combine + +public class Presenter: ObservableObject +where +Interactor.Request == Request, +Interactor.Response == Response { + + private var cancellables: Set = [] + private let _useCase: Interactor + + @Published public var item: Response? + @Published public var errorMessage: String = "" + @Published public var isLoading: Bool = false + @Published public var isError: Bool = false + + public init(useCase: Interactor){ + _useCase = useCase + } + + public func execute(request: Request?) { + isLoading = true + _useCase.execute(request: request) + .receive(on: RunLoop.main) + .sink(receiveCompletion: { completion in + switch completion { + case .failure(let error): + self.errorMessage = error.localizedDescription + self.isError = true + self.isLoading = false + case .finished: + self.isLoading = false + } + }, receiveValue: { item in + self.item = item + }) + .store(in: &cancellables) + } + +} diff --git a/Sources/Core/Utils/Prefs.swift b/Sources/Core/Utils/Prefs.swift new file mode 100644 index 0000000..cc595d1 --- /dev/null +++ b/Sources/Core/Utils/Prefs.swift @@ -0,0 +1,32 @@ +// +// File.swift +// +// +// Created by Iqbal Nur Haq on 11/01/23. +// + +import Foundation + +public class Prefs +{ + private let defaults = UserDefaults.standard + + private let keyAccessTokenPrefs = "tokenPrefs" + + public var accessTokenPrefs: String { + set { + defaults.setValue(newValue, forKey: keyAccessTokenPrefs) + } + get { + return defaults.string(forKey: keyAccessTokenPrefs) ?? "" + } + } + + public class var shared: Prefs { + struct Static { + static let instance = Prefs() + } + + return Static.instance + } +} diff --git a/Tests/CoreTests/CoreTests.swift b/Tests/CoreTests/CoreTests.swift new file mode 100644 index 0000000..a4c9d62 --- /dev/null +++ b/Tests/CoreTests/CoreTests.swift @@ -0,0 +1,11 @@ +import XCTest +@testable import Core + +final class CoreTests: XCTestCase { + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct + // results. + XCTAssertEqual(Core().text, "Hello, World!") + } +}