Skip to content

Commit

Permalink
Template Actions
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Usbergo committed May 19, 2020
1 parent af55b7f commit 28b427e
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 1 deletion.
4 changes: 4 additions & 0 deletions Sources/Store/Action.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ public extension ActionProtocol {
}

public final class UnspecifiedStore: Store<Void> { }




15 changes: 14 additions & 1 deletion Sources/Store/Store.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public protocol AnyStoreProtocol: class {
/// Notify all of the registered middleware services.
/// - note: See `MiddlewareType.onTransactionStateChange`.
func notifyMiddleware(transaction: TransactionProtocol)

/// Recursively traverse the parents until it founds one that matches the specified model type.
func parent<T>(type: T.Type) -> Store<T>?
}

public protocol StoreProtocol: AnyStoreProtocol {
Expand Down Expand Up @@ -115,7 +118,9 @@ open class Store<M>: StoreProtocol, ObservableObject {
// MARK: Children stores

/// Creates a store for a subtree of the wrapped model.
/// Similar to Redux `combineStores`.
/// As logic grows could be convient to split store into smaller one, still using the same
/// root model.
/// - note: Similar to Redux `combineStores`.
public func makeChildStore<M_1>(
keyPath: WritableKeyPath<M, M_1>,
create: (M_1) -> Store<M_1> = { Store<M_1>(model: $0) }
Expand All @@ -129,6 +134,14 @@ open class Store<M>: StoreProtocol, ObservableObject {
}
return childStore
}

/// Recursively traverse the parents until it founds one that matches the specified model type.
public func parent<T>(type: T.Type) -> Store<T>? {
if let parent = parent as? Store<T> {
return parent
}
return parent?.parent(type: type)
}

// MARK: Executing transactions

Expand Down
48 changes: 48 additions & 0 deletions Sources/Store/TemplateActions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Foundation
import os.log

// MARK: - Template Actions

/// General-purpose actions that can be applied to any store.
public struct TemplateAction {

public struct AssignKeyPath<M, V>: ActionProtocol {
public let keyPath: WritableKeyPath<M, V>
public let value: V

public func reduce(context: TransactionContext<Store<M>, Self>) {
defer { context.fulfill() }
context.reduceModel { model in model[keyPath: keyPath] = value }
}
}

public struct AssignOptionalKeyPath<M, V>: ActionProtocol {
public let keyPath: WritableKeyPath<M, V?>
public let value: V?

public func reduce(context: TransactionContext<Store<M>, Self>) {
defer { context.fulfill() }
context.reduceModel { model in model[keyPath: keyPath] = value }
}
}

public struct FilterArrayAtKeyPath<M, V: Collection, T>: ActionProtocol where V.Element == T {
public let keyPath: WritableKeyPath<M, V>
public let isIncluded: (T) -> Bool

public func reduce(context: TransactionContext<Store<M>, Self>) {
defer { context.fulfill() }
context.reduceModel { model in
guard var array = model[keyPath: keyPath] as? [T] else {
os_log(.error, log: OSLog.primary, " Arrays are the only collection type supported.")
return
}
array = array.filter(isIncluded)
// Trivial cast.
guard let collection = array as? V else { return }
model[keyPath: keyPath] = collection
}
}
}

}

0 comments on commit 28b427e

Please sign in to comment.