/* * Fluxor * Copyright (c) Morten Bjerg Gregersen 2020 * MIT license, see LICENSE file for details */ import Foundation /// A type which takes a `State` and `Action` returns a new `State`. public struct Reducer { /// An unique identifier used when registering/unregistering the `Reducer` on the `Store`. public let id: String /// A pure function which takes the a `State` and an `Action` and returns a new `State`. public let reduce: (inout State, Action) -> Void /** Creates a `Reducer` from a `reduce` function. The `reduce` function is a pure function which takes the a `State` and an `Action` and returns a new `State`. - Parameter reduce: The `reduce` function to create a `Reducer` from - Parameter state: The `State` to mutate - Parameter action: The `Action` dispatched */ public init(id: String = UUID().uuidString, reduce: @escaping (_ state: inout State, _ action: Action) -> Void) { self.id = id self.reduce = reduce } /** Creates a `Reducer` from a list of `ReduceOn`s. - Parameter reduceOns: The `ReduceOn`s which the created `Reducer` should contain */ public init(id: String = UUID().uuidString, _ reduceOns: ReduceOn...) { self.id = id self.reduce = { state, action in reduceOns.forEach { $0.reduce(&state, action) } } } } /// A part of a `Reducer` which only gets triggered on certain `Action`s or `ActionTemplate`s. public struct ReduceOn { /// A pure function which takes the a `State` and an `Action` and returns a new `State`. public let reduce: (inout State, Action) -> Void /** Creates a `ReduceOn` which only runs `reduce` with actions of the type specificed in `actionType`. - Parameter actionType: The type of `Action` to filter on - Parameter reduce: A pure function which takes a `State` and an `Action` and returns a new `State`. - Parameter state: The `State` to mutate - Parameter action: The `Action` dispatched */ public init(_ actionType: A.Type, reduce: @escaping (_ state: inout State, _ action: A) -> Void) { self.reduce = { state, action in guard let action = action as? A else { return } reduce(&state, action) } } /** Creates a `ReduceOn` which only runs `reduce` with actions created from the specificed `ActionTemplate`s. - Parameter actionTemplates: The `ActionTemplate`s to filter on - Parameter reduce: A pure function which takes a `State` and an `Action` and returns a new `State`. - Parameter state: The `State` to mutate - Parameter action: The `Action` dispatched */ public init(_ actionTemplates: ActionTemplate..., reduce: @escaping (_ state: inout State, _ action: AnonymousAction) -> Void) { self.reduce = { state, action in guard let anonymousAction = action as? AnonymousAction else { return } guard actionTemplates.contains(where: { anonymousAction.wasCreated(from: $0) }) else { return } reduce(&state, anonymousAction) } } }