Skip to content

Commit

Permalink
Merge pull request #1 from helloItsHEssam/feature/modularization-domain
Browse files Browse the repository at this point in the history
Pull request from 'Feature/modularization-domain' to 'Feature/modularization'
  • Loading branch information
helloItsHEssam authored Nov 4, 2023
2 parents a095d26 + f3ecb97 commit 4dd9b83
Show file tree
Hide file tree
Showing 18 changed files with 790 additions and 1 deletion.
27 changes: 27 additions & 0 deletions .github/workflows/Domain.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Domain Layer

on:
pull_request:
branches:
- '*'
- '*/*'

jobs:
build:
runs-on: macos-13

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up SwiftLint
run: brew install swiftlint

- name: Lint code
run: swiftlint

- name: run unit test
run: |
cd Domain/Sources/
swift build
swift test
9 changes: 9 additions & 0 deletions Domain/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
29 changes: 29 additions & 0 deletions Domain/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// swift-tools-version: 5.8
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Domain",
platforms: [.iOS(.v14), .macOS(.v10_15)],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "Domain",
targets: ["Domain"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
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: "Domain",
dependencies: []),
.testTarget(
name: "DomainTests",
dependencies: ["Domain"]),
]
)
3 changes: 3 additions & 0 deletions Domain/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Domain

A description of this package.
19 changes: 19 additions & 0 deletions Domain/Sources/Domain/Entities/Card.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Card.swift
//
//
// Created by Hessam Mahdiabadi on 11/4/23.
//

import Foundation

public struct Card {

public var cardNumber: String?
public var cardType: String?

public init(cardNumber: String?, cardType: String?) {
self.cardNumber = cardNumber
self.cardType = cardType
}
}
19 changes: 19 additions & 0 deletions Domain/Sources/Domain/Entities/CardTransferCount.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// CardTransferCount.swift
//
//
// Created by Hessam Mahdiabadi on 11/4/23.
//

import Foundation

public struct CardTransferCount {

public var numberOfTransfers: Int?
public var totalTransfer: Int?

public init(numberOfTransfers: Int?, totalTransfer: Int?) {
self.numberOfTransfers = numberOfTransfers
self.totalTransfer = totalTransfer
}
}
21 changes: 21 additions & 0 deletions Domain/Sources/Domain/Entities/Person.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// Person.swift
//
//
// Created by Hessam Mahdiabadi on 11/4/23.
//

import Foundation

public struct Person {

public var name: String?
public var emial: String?
public var avatar: String?

public init(name: String?, emial: String?, avatar: String?) {
self.name = name
self.emial = emial
self.avatar = avatar
}
}
39 changes: 39 additions & 0 deletions Domain/Sources/Domain/Entities/PersonBankAccount.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// PersonBankAccount.swift
//
//
// Created by Hessam Mahdiabadi on 11/4/23.
//

import Foundation

public struct PersonBankAccount: Identifiable {

public var id: String {
card?.cardNumber ?? UUID().uuidString
}
public var person: Person?
public var card: Card?
public var cardTransferCount: CardTransferCount?
public var note: String?
public var lastDateTransfer: Date?
public private(set) var isFavorite: Bool = false
var indexAtList: Int = 0

public init(person: Person?, card: Card?, cardTransferCount: CardTransferCount?,
note: String?, lastDateTransfer: Date?) {
self.person = person
self.card = card
self.cardTransferCount = cardTransferCount
self.note = note
self.lastDateTransfer = lastDateTransfer
}

public mutating func update(favoriteStatus isFavorite: Bool) {
self.isFavorite = isFavorite
}

mutating func update(indexAtList index: Int) {
self.indexAtList = index
}
}
35 changes: 35 additions & 0 deletions Domain/Sources/Domain/Error/PersonBankAccountError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// PersonBankAccountError.swift
//
//
// Created by Hessam Mahdiabadi on 11/4/23.
//

import Foundation

public enum PersonBankAccountError: Error {

case cannotSavePersonAccountToFavorites
case cannotRemovePersonAccountFromFavorites
case cannotFetchPersonAccounts
case cannotFetchFavoritePersonAccounts
case unexpectedError

var errorDescription: String? {
switch self {
case .cannotSavePersonAccountToFavorites:
return "Failed to save person accounts to favorites"

case .cannotRemovePersonAccountFromFavorites:
return "Failed to remove person account from favorites"

case .cannotFetchPersonAccounts:
return "Failed to fetch person accounts"

case .cannotFetchFavoritePersonAccounts:
return "Failed to fetch favorite person accounts"

case .unexpectedError: return "Unexpected error"
}
}
}
55 changes: 55 additions & 0 deletions Domain/Sources/Domain/Extension/AnyPublisher+async.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// AnyPublisher+async.swift
//
//
// Created by Hessam Mahdiabadi on 11/4/23.
//

import Combine

extension AnyPublisher where Failure == PersonBankAccountError {
struct Subscriber {
fileprivate let send: (Output) -> Void
fileprivate let complete: (Subscribers.Completion<Failure>) -> Void

func send(_ value: Output) {
self.send(value)
}
func send(completion: Subscribers.Completion<Failure>) {
self.complete(completion)
}
}

init(_ closure: (Subscriber) -> AnyCancellable) {
let subject = PassthroughSubject<Output, Failure>()

let subscriber = Subscriber(
send: subject.send,
complete: subject.send(completion:)
)
let cancel = closure(subscriber)

self = subject
.handleEvents(receiveCancel: cancel.cancel)
.eraseToAnyPublisher()
}
}

extension AnyPublisher where Failure == PersonBankAccountError {
init(taskPriority: TaskPriority? = nil, asyncFunc: @escaping () async throws -> Output) {
self.init { subscriber in
let task = Task(priority: taskPriority) {
do {
subscriber.send(try await asyncFunc())
subscriber.send(completion: .finished)
} catch {
let personError = error as? PersonBankAccountError ?? .unexpectedError
subscriber.send(completion: .failure(personError))
}
}
return AnyCancellable {
task.cancel()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// PersonBankAccountRepository.swift.swift
//
//
// Created by Hessam Mahdiabadi on 11/4/23.
//

import Foundation

public protocol PersonBankAccountRepository {

func fetchPersonAccounts(withOffest offset: Int) async throws -> [PersonBankAccount]
func fetchFavoritePersonAccounts() async throws -> [PersonBankAccount]
func savePersonAccountToFavorites(_ personBankAccount: PersonBankAccount) async throws -> PersonBankAccount
func removePersonAccountFromFavorites(_ personBankAccount: PersonBankAccount) async throws -> PersonBankAccount
func updatefavoriteStatusForPersonAccount(_ personBankAccount: PersonBankAccount) async -> PersonBankAccount
}
19 changes: 19 additions & 0 deletions Domain/Sources/Domain/UseCases/PersonBankAccountUseCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// PersonBankAccountUseCase.swift
//
//
// Created by Hessam Mahdiabadi on 11/4/23.
//

import Foundation
import Combine

public protocol PersonBankAccountUseCase {

func fetchPersonAccounts(withOffest offset: Int) -> AnyPublisher<[PersonBankAccount], PersonBankAccountError>
func fetchFavoritePersonAccounts() -> AnyPublisher<[PersonBankAccount], PersonBankAccountError>
func savePersonAccountToFavorites(_ personBankAccount: PersonBankAccount)
-> AnyPublisher<PersonBankAccount, PersonBankAccountError>
func removePersonAccountFromFavorites(_ personBankAccount: PersonBankAccount)
-> AnyPublisher<PersonBankAccount, PersonBankAccountError>
}
Loading

0 comments on commit 4dd9b83

Please sign in to comment.