/* * Fluxor * Copyright (c) Morten Bjerg Gregersen 2020 * MIT license, see LICENSE file for details */ #if USE_OPENCOMBINE import OpenCombine #else import Combine #endif /** A side effect that happens as a response to a dispatched `Action`. An `Effect` can: - give a new `Action` to dispatch (a `dispatchingOne` effect) - give an array of new `Action`s to dispatch (a `dispatchingMultiple` effect) - give nothing (a `nonDispatching` effect) */ public enum Effect { /// An `Effect` that publishes an `Action` to dispatch. case dispatchingOne(_ publisher: (AnyPublisher, Environment) -> AnyPublisher) /// An `Effect` that publishes multiple `Action`s to dispatch. case dispatchingMultiple(_ publisher: (AnyPublisher, Environment) -> AnyPublisher<[Action], Never>) /// An `Effect` that handles the action but doesn't publish a new `Action`. case nonDispatching(_ cancellable: (AnyPublisher, Environment) -> AnyCancellable) } /** A collection of `Effect`s. The only requirement for the protocol is to specify the type of the `Environment` which should be used in the `Effect`s. The properties have default implementations. */ public protocol Effects { /// The environment set up in the `Store` passed to every `Effect`. associatedtype Environment /** The `Effect`s to register on the `Store`. The default implementation takes all the `Effect`s in the type, It is possible to implement the property manually to only enable a subset of `Effect`s to enable. */ var enabledEffects: [Effect] { get } /// The identifier for the `Effects`. The default implementation is just the name of the type. static var id: String { get } } public extension Effects { var enabledEffects: [Effect] { Mirror(reflecting: self).children.compactMap { $0.value as? Effect } } static var id: String { .init(describing: Self.self) } }