feat: Adds TCA Helpers, some are wip.
This commit is contained in:
@@ -45,6 +45,12 @@ let package = Package(
|
|||||||
),
|
),
|
||||||
.target(name: "SharedModels"),
|
.target(name: "SharedModels"),
|
||||||
.target(name: "Styleguide"),
|
.target(name: "Styleguide"),
|
||||||
|
.target(
|
||||||
|
name: "TCAHelpers",
|
||||||
|
dependencies: [
|
||||||
|
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||||
|
]
|
||||||
|
),
|
||||||
.testTarget(
|
.testTarget(
|
||||||
name: "EstimatedPressureTests",
|
name: "EstimatedPressureTests",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
|||||||
25
Sources/TCAHelpers/Effect+fail.swift
Normal file
25
Sources/TCAHelpers/Effect+fail.swift
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import ComposableArchitecture
|
||||||
|
import OSLog
|
||||||
|
|
||||||
|
extension Effect {
|
||||||
|
public static func fail(
|
||||||
|
prefix: String = "Failed error:",
|
||||||
|
error: Error,
|
||||||
|
logger: Logger? = nil
|
||||||
|
) -> Self {
|
||||||
|
let message = "\(prefix) \(error)"
|
||||||
|
XCTFail("\(message)")
|
||||||
|
logger?.error("\(message)")
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func fail(
|
||||||
|
_ message: String,
|
||||||
|
logger: Logger? = nil
|
||||||
|
) -> Self {
|
||||||
|
XCTFail("\(message)")
|
||||||
|
logger?.error("\(message)")
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
40
Sources/TCAHelpers/Effect+receive.swift
Normal file
40
Sources/TCAHelpers/Effect+receive.swift
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import ComposableArchitecture
|
||||||
|
|
||||||
|
public protocol ReceiveAction<ReceiveAction> {
|
||||||
|
associatedtype ReceiveAction
|
||||||
|
static func receive(_ result: TaskResult<ReceiveAction>) -> Self
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Effect where Action: ReceiveAction {
|
||||||
|
|
||||||
|
public static func receive(
|
||||||
|
_ operation: @escaping () async throws -> Action.ReceiveAction
|
||||||
|
) -> Self {
|
||||||
|
.run { send in
|
||||||
|
await send(.receive(
|
||||||
|
TaskResult { try await operation() }
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func receive<T>(
|
||||||
|
_ operation: @escaping () async throws -> T,
|
||||||
|
transform: @escaping (T) -> Action.ReceiveAction
|
||||||
|
) -> Self {
|
||||||
|
.run { send in
|
||||||
|
await send(.receive(
|
||||||
|
TaskResult { try await operation() }
|
||||||
|
.map(transform)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func receive<T>(
|
||||||
|
_ toReceiveAction: CaseKeyPath<Action.ReceiveAction, T>,
|
||||||
|
_ operation: @escaping () async throws -> T
|
||||||
|
) -> Self {
|
||||||
|
return .receive(operation) {
|
||||||
|
AnyCasePath(toReceiveAction).embed($0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
51
Sources/TCAHelpers/ReceiveFailureReducer.swift
Normal file
51
Sources/TCAHelpers/ReceiveFailureReducer.swift
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import ComposableArchitecture
|
||||||
|
import OSLog
|
||||||
|
|
||||||
|
public struct _ReceiveFailureReducer<State, Action>: Reducer {
|
||||||
|
|
||||||
|
@usableFromInline
|
||||||
|
let toReceiveActionError: (Action) -> Error?
|
||||||
|
|
||||||
|
@usableFromInline
|
||||||
|
let logger: Logger
|
||||||
|
|
||||||
|
@inlinable
|
||||||
|
public init<ViewAction: ReceiveAction>(
|
||||||
|
action toReceiveAction: CaseKeyPath<Action, ViewAction>,
|
||||||
|
logger: Logger
|
||||||
|
) {
|
||||||
|
self.init(
|
||||||
|
internal: { action in
|
||||||
|
if case let .receive(.failure(error)) = AnyCasePath(toReceiveAction).extract(from: action) {
|
||||||
|
return error
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
logger: logger
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@usableFromInline
|
||||||
|
init(internal toReceiveActionError: @escaping (Action) -> Error?, logger: Logger) {
|
||||||
|
self.toReceiveActionError = toReceiveActionError
|
||||||
|
self.logger = logger
|
||||||
|
}
|
||||||
|
|
||||||
|
@inlinable
|
||||||
|
public func reduce(
|
||||||
|
into state: inout State,
|
||||||
|
action: Action
|
||||||
|
) -> Effect<Action> {
|
||||||
|
guard let error = toReceiveActionError(action) else { return .none }
|
||||||
|
return .fail(error: error, logger: logger)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Reducer where Action: ReceiveAction, Action: CasePathable {
|
||||||
|
public func onFail(_ logger: Logger) -> _ReceiveFailureReducer<State, Action, Action> {
|
||||||
|
_ReceiveFailureReducer(
|
||||||
|
action: \.receive,
|
||||||
|
logger: logger
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user