feat: Adds TCA Helpers, some are wip.

This commit is contained in:
2024-05-28 17:01:30 -04:00
parent 187a682a63
commit 24211187bf
4 changed files with 122 additions and 0 deletions

View File

@@ -45,6 +45,12 @@ let package = Package(
),
.target(name: "SharedModels"),
.target(name: "Styleguide"),
.target(
name: "TCAHelpers",
dependencies: [
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
]
),
.testTarget(
name: "EstimatedPressureTests",
dependencies: [

View 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
}
}

View 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)
}
}
}

View 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
)
}
}