MiddlewareReaderProtocol
public protocol MiddlewareReaderProtocol
A protocol to generalize MiddlewareReader. Unless you look for some very special behaviour, you should use MiddlewareReader directly which provides everything needed for your Middleware dependency injection.
-
Dependencies to inject in the middleware. This is equivalent to the parameters in a middleware initializer, usually a tuple with multiple dependencies separated by comma. In a function
(Dependencies) -> MiddlewareType
, this is at the left-hand side to the arrow.Declaration
Swift
associatedtype Dependencies
-
The resulting middleware after the dependencies are injected. In a function
(Dependencies) -> MiddlewareType
, this is at the right-hand side to the arrow.Declaration
Swift
associatedtype MiddlewareType : MiddlewareProtocol
-
An initializer function that, given the dependencies in the Middleware’s init, will give the Middleware instance When inject is called, your MiddlewareReader materializes into a Middleware.
Declaration
Swift
var inject: (Dependencies) -> MiddlewareType { get }
-
Allows to define a middleware initializer and store this initializer function until we have the dependencies to call it. This allows us to postpone the dependency injection and compose middlewares that are not even materialized yet.
Declaration
Swift
init(inject: @escaping (Dependencies) -> MiddlewareType)
Parameters
inject
An initializer function that, given the dependencies in the Middleware’s init, will give the Middleware instance When inject is called, your MiddlewareReader materializes into a Middleware.
-
<>(_:
Extension method_: ) Compose two Middlewares that are not officially Semigroups and not necessarily the same Middleware type, into a
ComposedMiddleware
that holds both before even materializing them into real instances. As most Middlewares don’t need to returnSelf
when grouped together, and it’s perfectly reasonable to compose middlewares of different types, this option is more flexible than the Semigroup composition.The only requirements are that:
- both middleware readers must depend on the same Dependencies type
- both resulting middlewares should match their input action, output action and state types
Therefore, you should lift them first before composing them. Luckily this is possible to be done with MiddlewareReader.
Declaration
Swift
public static func <> <OtherMiddleware: MiddlewareProtocol>(lhs: Self, rhs: MiddlewareReader<Dependencies, OtherMiddleware>) -> MiddlewareReader<Dependencies, ComposedMiddleware<MiddlewareType.InputActionType, MiddlewareType.OutputActionType, MiddlewareType.StateType>> where OtherMiddleware.InputActionType == MiddlewareType.InputActionType, OtherMiddleware.OutputActionType == MiddlewareType.OutputActionType, OtherMiddleware.StateType == MiddlewareType.StateType
Parameters
lhs
middleware reader that will generate a middleware which runs first
rhs
middleware reader that will generate a middleware which runs last
Return Value
a composed Middleware Reader that, once injected with dependencies, will produce a ComposedMiddleware that runs first the left and then the right middleware
-
identity
Extension methodAn identity MiddlewareReader ignores whatever Dependencies are given and simply return an identity Middleware. Composing any given middleware reader “A” with the identity middleware reader will be exactly the same as composing in the other order and also exactly the same as only the middleware reader “A” alone, which means, it doesn’t change anything in the MiddlewareReader “A” or its resulting Middleware, regardless of the order it was composed to.
Declaration
Swift
public static var identity: MiddlewareReader<Self.Dependencies, IdentityMiddleware<Self.MiddlewareType.InputActionType, Self.MiddlewareType.OutputActionType, Self.MiddlewareType.StateType>> { get }
-
lift(inputAction:
Extension methodoutputAction: state: dependencies: ) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalDependencies, GlobalInputActionType, GlobalOutputActionType, GlobalStateType>( inputAction inputActionMap: @escaping (GlobalInputActionType) -> MiddlewareType.InputActionType?, outputAction outputActionMap: @escaping (MiddlewareType.OutputActionType) -> GlobalOutputActionType, state stateMap: @escaping (GlobalStateType) -> MiddlewareType.StateType, dependencies dependenciesMap: @escaping (GlobalDependencies) -> Dependencies ) -> MiddlewareReader<GlobalDependencies, LiftMiddleware<GlobalInputActionType, GlobalOutputActionType, GlobalStateType, MiddlewareType>>
Parameters
inputActionMap
once app actions (global) are in the Store chain, this function will pick only those that are relevant for this middleware or return nil in case they should be ignored. Global Actions that can be transformed into local actions will be forwarded to the middleware. This is usually implemented like:
inputActionMap: { globalAction in guard case let AppAction.someLocalCase(localAction) = globalAction else { return nil } return localAction }
You can use enum properties code generators to simplify this call to a simpleinputActionMap: \AppAction.someLocalCase
outputActionMap
once this middleware dispatched some actions, this function should tell how to wrap each action to a more global action entity, to be forwarded to the Store chain. This is usually implemented like:
outputActionMap: { actionFromMiddleware in return AppAction.someLocalCase(actionFromMiddleware) }
Or for a single-level enum, the short-formoutputActionMap: AppAction.someLocalCase
stateMap
this middleware may read only small portions of the whole app state. Global App State will be given so you can pick only the parts relevant for this middleware. This is usually implemented like:
stateMap: { globalState in return globalState.someProperty }
Or the KeyPath form:stateMap: \AppState.someProperty
dependenciesMap
this middleware may depend on only a small amount of dependencies, not all the dependencies in your app. Given that there’s a
GlobalDependencies
struct holding the whole world of dependencies, this function can pick only the dependencies needed for this middleware. This is usually implemented like:dependenciesMap: { (world: World) in return (urlSession: world.urlSession, decoder: world.jsonDecoder) }
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(outputAction:
Extension methodstate: dependencies: ) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalDependencies, GlobalOutputActionType, GlobalStateType>( outputAction outputActionMap: @escaping (MiddlewareType.OutputActionType) -> GlobalOutputActionType, state stateMap: @escaping (GlobalStateType) -> MiddlewareType.StateType, dependencies dependenciesMap: @escaping (GlobalDependencies) -> Dependencies ) -> MiddlewareReader< GlobalDependencies, LiftMiddleware<MiddlewareType.InputActionType, GlobalOutputActionType, GlobalStateType, MiddlewareType> >
Parameters
outputActionMap
once this middleware dispatched some actions, this function should tell how to wrap each action to a more global action entity, to be forwarded to the Store chain. This is usually implemented like:
outputActionMap: { actionFromMiddleware in return AppAction.someLocalCase(actionFromMiddleware) }
Or for a single-level enum, the short-formoutputActionMap: AppAction.someLocalCase
stateMap
this middleware may read only small portions of the whole app state. Global App State will be given so you can pick only the parts relevant for this middleware. This is usually implemented like:
stateMap: { globalState in return globalState.someProperty }
Or the KeyPath form:stateMap: \AppState.someProperty
dependenciesMap
this middleware may depend on only a small amount of dependencies, not all the dependencies in your app. Given that there’s a
GlobalDependencies
struct holding the whole world of dependencies, this function can pick only the dependencies needed for this middleware. This is usually implemented like:dependenciesMap: { (world: World) in return (urlSession: world.urlSession, decoder: world.jsonDecoder) }
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(inputAction:
Extension methodstate: dependencies: ) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalDependencies, GlobalInputActionType, GlobalStateType>( inputAction inputActionMap: @escaping (GlobalInputActionType) -> MiddlewareType.InputActionType?, state stateMap: @escaping (GlobalStateType) -> MiddlewareType.StateType, dependencies dependenciesMap: @escaping (GlobalDependencies) -> Dependencies ) -> MiddlewareReader< GlobalDependencies, LiftMiddleware<GlobalInputActionType, MiddlewareType.OutputActionType, GlobalStateType, MiddlewareType> >
Parameters
inputActionMap
once app actions (global) are in the Store chain, this function will pick only those that are relevant for this middleware or return nil in case they should be ignored. Global Actions that can be transformed into local actions will be forwarded to the middleware. This is usually implemented like:
inputActionMap: { globalAction in guard case let AppAction.someLocalCase(localAction) = globalAction else { return nil } return localAction }
You can use enum properties code generators to simplify this call to a simpleinputActionMap: \AppAction.someLocalCase
stateMap
this middleware may read only small portions of the whole app state. Global App State will be given so you can pick only the parts relevant for this middleware. This is usually implemented like:
stateMap: { globalState in return globalState.someProperty }
Or the KeyPath form:stateMap: \AppState.someProperty
dependenciesMap
this middleware may depend on only a small amount of dependencies, not all the dependencies in your app. Given that there’s a
GlobalDependencies
struct holding the whole world of dependencies, this function can pick only the dependencies needed for this middleware. This is usually implemented like:dependenciesMap: { (world: World) in return (urlSession: world.urlSession, decoder: world.jsonDecoder) }
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(inputAction:
Extension methodoutputAction: dependencies: ) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalDependencies, GlobalInputActionType, GlobalOutputActionType>( inputAction inputActionMap: @escaping (GlobalInputActionType) -> MiddlewareType.InputActionType?, outputAction outputActionMap: @escaping (MiddlewareType.OutputActionType) -> GlobalOutputActionType, dependencies dependenciesMap: @escaping (GlobalDependencies) -> Dependencies ) -> MiddlewareReader< GlobalDependencies, LiftMiddleware<GlobalInputActionType, GlobalOutputActionType, MiddlewareType.StateType, MiddlewareType> >
Parameters
inputActionMap
once app actions (global) are in the Store chain, this function will pick only those that are relevant for this middleware or return nil in case they should be ignored. Global Actions that can be transformed into local actions will be forwarded to the middleware. This is usually implemented like:
inputActionMap: { globalAction in guard case let AppAction.someLocalCase(localAction) = globalAction else { return nil } return localAction }
You can use enum properties code generators to simplify this call to a simpleinputActionMap: \AppAction.someLocalCase
outputActionMap
once this middleware dispatched some actions, this function should tell how to wrap each action to a more global action entity, to be forwarded to the Store chain. This is usually implemented like:
outputActionMap: { actionFromMiddleware in return AppAction.someLocalCase(actionFromMiddleware) }
Or for a single-level enum, the short-formoutputActionMap: AppAction.someLocalCase
dependenciesMap
this middleware may depend on only a small amount of dependencies, not all the dependencies in your app. Given that there’s a
GlobalDependencies
struct holding the whole world of dependencies, this function can pick only the dependencies needed for this middleware. This is usually implemented like:dependenciesMap: { (world: World) in return (urlSession: world.urlSession, decoder: world.jsonDecoder) }
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(inputAction:
Extension methodoutputAction: state: ) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalInputActionType, GlobalOutputActionType, GlobalStateType>( inputAction inputActionMap: @escaping (GlobalInputActionType) -> MiddlewareType.InputActionType?, outputAction outputActionMap: @escaping (MiddlewareType.OutputActionType) -> GlobalOutputActionType, state stateMap: @escaping (GlobalStateType) -> MiddlewareType.StateType ) -> MiddlewareReader<Dependencies, LiftMiddleware<GlobalInputActionType, GlobalOutputActionType, GlobalStateType, MiddlewareType>>
Parameters
inputActionMap
once app actions (global) are in the Store chain, this function will pick only those that are relevant for this middleware or return nil in case they should be ignored. Global Actions that can be transformed into local actions will be forwarded to the middleware. This is usually implemented like:
inputActionMap: { globalAction in guard case let AppAction.someLocalCase(localAction) = globalAction else { return nil } return localAction }
You can use enum properties code generators to simplify this call to a simpleinputActionMap: \AppAction.someLocalCase
outputActionMap
once this middleware dispatched some actions, this function should tell how to wrap each action to a more global action entity, to be forwarded to the Store chain. This is usually implemented like:
outputActionMap: { actionFromMiddleware in return AppAction.someLocalCase(actionFromMiddleware) }
Or for a single-level enum, the short-formoutputActionMap: AppAction.someLocalCase
stateMap
this middleware may read only small portions of the whole app state. Global App State will be given so you can pick only the parts relevant for this middleware. This is usually implemented like:
stateMap: { globalState in return globalState.someProperty }
Or the KeyPath form:stateMap: \AppState.someProperty
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(state:
Extension methoddependencies: ) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalDependencies, GlobalStateType>( state stateMap: @escaping (GlobalStateType) -> MiddlewareType.StateType, dependencies dependenciesMap: @escaping (GlobalDependencies) -> Dependencies ) -> MiddlewareReader< GlobalDependencies, LiftMiddleware<MiddlewareType.InputActionType, MiddlewareType.OutputActionType, GlobalStateType, MiddlewareType> >
Parameters
stateMap
this middleware may read only small portions of the whole app state. Global App State will be given so you can pick only the parts relevant for this middleware. This is usually implemented like:
stateMap: { globalState in return globalState.someProperty }
Or the KeyPath form:stateMap: \AppState.someProperty
dependenciesMap
this middleware may depend on only a small amount of dependencies, not all the dependencies in your app. Given that there’s a
GlobalDependencies
struct holding the whole world of dependencies, this function can pick only the dependencies needed for this middleware. This is usually implemented like:dependenciesMap: { (world: World) in return (urlSession: world.urlSession, decoder: world.jsonDecoder) }
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(outputAction:
Extension methoddependencies: ) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalDependencies, GlobalOutputActionType>( outputAction outputActionMap: @escaping (MiddlewareType.OutputActionType) -> GlobalOutputActionType, dependencies dependenciesMap: @escaping (GlobalDependencies) -> Dependencies ) -> MiddlewareReader< GlobalDependencies, LiftMiddleware<MiddlewareType.InputActionType, GlobalOutputActionType, MiddlewareType.StateType, MiddlewareType> >
Parameters
outputActionMap
once this middleware dispatched some actions, this function should tell how to wrap each action to a more global action entity, to be forwarded to the Store chain. This is usually implemented like:
outputActionMap: { actionFromMiddleware in return AppAction.someLocalCase(actionFromMiddleware) }
Or for a single-level enum, the short-formoutputActionMap: AppAction.someLocalCase
dependenciesMap
this middleware may depend on only a small amount of dependencies, not all the dependencies in your app. Given that there’s a
GlobalDependencies
struct holding the whole world of dependencies, this function can pick only the dependencies needed for this middleware. This is usually implemented like:dependenciesMap: { (world: World) in return (urlSession: world.urlSession, decoder: world.jsonDecoder) }
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(outputAction:
Extension methodstate: ) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalOutputActionType, GlobalStateType>( outputAction outputActionMap: @escaping (MiddlewareType.OutputActionType) -> GlobalOutputActionType, state stateMap: @escaping (GlobalStateType) -> MiddlewareType.StateType ) -> MiddlewareReader<Dependencies, LiftMiddleware<MiddlewareType.InputActionType, GlobalOutputActionType, GlobalStateType, MiddlewareType>>
Parameters
outputActionMap
once this middleware dispatched some actions, this function should tell how to wrap each action to a more global action entity, to be forwarded to the Store chain. This is usually implemented like:
outputActionMap: { actionFromMiddleware in return AppAction.someLocalCase(actionFromMiddleware) }
Or for a single-level enum, the short-formoutputActionMap: AppAction.someLocalCase
stateMap
this middleware may read only small portions of the whole app state. Global App State will be given so you can pick only the parts relevant for this middleware. This is usually implemented like:
stateMap: { globalState in return globalState.someProperty }
Or the KeyPath form:stateMap: \AppState.someProperty
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(inputAction:
Extension methoddependencies: ) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalDependencies, GlobalInputActionType>( inputAction inputActionMap: @escaping (GlobalInputActionType) -> MiddlewareType.InputActionType?, dependencies dependenciesMap: @escaping (GlobalDependencies) -> Dependencies ) -> MiddlewareReader< GlobalDependencies, LiftMiddleware<GlobalInputActionType, MiddlewareType.OutputActionType, MiddlewareType.StateType, MiddlewareType> >
Parameters
inputActionMap
once app actions (global) are in the Store chain, this function will pick only those that are relevant for this middleware or return nil in case they should be ignored. Global Actions that can be transformed into local actions will be forwarded to the middleware. This is usually implemented like:
inputActionMap: { globalAction in guard case let AppAction.someLocalCase(localAction) = globalAction else { return nil } return localAction }
You can use enum properties code generators to simplify this call to a simpleinputActionMap: \AppAction.someLocalCase
dependenciesMap
this middleware may depend on only a small amount of dependencies, not all the dependencies in your app. Given that there’s a
GlobalDependencies
struct holding the whole world of dependencies, this function can pick only the dependencies needed for this middleware. This is usually implemented like:dependenciesMap: { (world: World) in return (urlSession: world.urlSession, decoder: world.jsonDecoder) }
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(inputAction:
Extension methodstate: ) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalInputActionType, GlobalStateType>( inputAction inputActionMap: @escaping (GlobalInputActionType) -> MiddlewareType.InputActionType?, state stateMap: @escaping (GlobalStateType) -> MiddlewareType.StateType ) -> MiddlewareReader<Dependencies, LiftMiddleware<GlobalInputActionType, MiddlewareType.OutputActionType, GlobalStateType, MiddlewareType>>
Parameters
inputActionMap
once app actions (global) are in the Store chain, this function will pick only those that are relevant for this middleware or return nil in case they should be ignored. Global Actions that can be transformed into local actions will be forwarded to the middleware. This is usually implemented like:
inputActionMap: { globalAction in guard case let AppAction.someLocalCase(localAction) = globalAction else { return nil } return localAction }
You can use enum properties code generators to simplify this call to a simpleinputActionMap: \AppAction.someLocalCase
stateMap
this middleware may read only small portions of the whole app state. Global App State will be given so you can pick only the parts relevant for this middleware. This is usually implemented like:
stateMap: { globalState in return globalState.someProperty }
Or the KeyPath form:stateMap: \AppState.someProperty
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(inputAction:
Extension methodoutputAction: ) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalInputActionType, GlobalOutputActionType>( inputAction inputActionMap: @escaping (GlobalInputActionType) -> MiddlewareType.InputActionType?, outputAction outputActionMap: @escaping (MiddlewareType.OutputActionType) -> GlobalOutputActionType ) -> MiddlewareReader<Dependencies, LiftMiddleware<GlobalInputActionType, GlobalOutputActionType, MiddlewareType.StateType, MiddlewareType>>
Parameters
inputActionMap
once app actions (global) are in the Store chain, this function will pick only those that are relevant for this middleware or return nil in case they should be ignored. Global Actions that can be transformed into local actions will be forwarded to the middleware. This is usually implemented like:
inputActionMap: { globalAction in guard case let AppAction.someLocalCase(localAction) = globalAction else { return nil } return localAction }
You can use enum properties code generators to simplify this call to a simpleinputActionMap: \AppAction.someLocalCase
outputActionMap
once this middleware dispatched some actions, this function should tell how to wrap each action to a more global action entity, to be forwarded to the Store chain. This is usually implemented like:
outputActionMap: { actionFromMiddleware in return AppAction.someLocalCase(actionFromMiddleware) }
Or for a single-level enum, the short-formoutputActionMap: AppAction.someLocalCase
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(state:
Extension method) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalStateType>( state stateMap: @escaping (GlobalStateType) -> MiddlewareType.StateType ) -> MiddlewareReader< Dependencies, LiftMiddleware<MiddlewareType.InputActionType, MiddlewareType.OutputActionType, GlobalStateType, MiddlewareType> >
Parameters
stateMap
this middleware may read only small portions of the whole app state. Global App State will be given so you can pick only the parts relevant for this middleware. This is usually implemented like:
stateMap: { globalState in return globalState.someProperty }
Or the KeyPath form:stateMap: \AppState.someProperty
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(dependencies:
Extension method) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalDependencies>( dependencies dependenciesMap: @escaping (GlobalDependencies) -> Dependencies ) -> MiddlewareReader<GlobalDependencies, MiddlewareType>
Parameters
dependenciesMap
this middleware may depend on only a small amount of dependencies, not all the dependencies in your app. Given that there’s a
GlobalDependencies
struct holding the whole world of dependencies, this function can pick only the dependencies needed for this middleware. This is usually implemented like:dependenciesMap: { (world: World) in return (urlSession: world.urlSession, decoder: world.jsonDecoder) }
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(outputAction:
Extension method) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalOutputActionType>( outputAction outputActionMap: @escaping (MiddlewareType.OutputActionType) -> GlobalOutputActionType ) -> MiddlewareReader< Dependencies, LiftMiddleware<MiddlewareType.InputActionType, GlobalOutputActionType, MiddlewareType.StateType, MiddlewareType> >
Parameters
outputActionMap
once this middleware dispatched some actions, this function should tell how to wrap each action to a more global action entity, to be forwarded to the Store chain. This is usually implemented like:
outputActionMap: { actionFromMiddleware in return AppAction.someLocalCase(actionFromMiddleware) }
Or for a single-level enum, the short-formoutputActionMap: AppAction.someLocalCase
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies.
-
lift(inputAction:
Extension method) All you need to compose totally different middlewares. Using lift you can match all 4 parameters of a middleware and once they have common ground, you are able to compose them. These 4 parameters are:
- Input Actions for the Middleware
- Output Actions from the Middleware
- Input State for the Middleware
Input Dependencies for the Middleware, through its MiddlewareReader dependency injection.
Declaration
Swift
public func lift<GlobalInputActionType>( inputAction inputActionMap: @escaping (GlobalInputActionType) -> MiddlewareType.InputActionType? ) -> MiddlewareReader< Dependencies, LiftMiddleware<GlobalInputActionType, MiddlewareType.OutputActionType, MiddlewareType.StateType, MiddlewareType> >
Parameters
inputActionMap
once app actions (global) are in the Store chain, this function will pick only those that are relevant for this middleware or return nil in case they should be ignored. Global Actions that can be transformed into local actions will be forwarded to the middleware. This is usually implemented like:
inputActionMap: { globalAction in guard case let AppAction.someLocalCase(localAction) = globalAction else { return nil } return localAction }
You can use enum properties code generators to simplify this call to a simpleinputActionMap: \AppAction.someLocalCase
Return Value
a
MiddlewareReader
that works on global types, so it can be composed with other MiddlewareReaders matching same global types even before injecting the dependencies. -
mapMiddleware(_:
Extension method) Maps the
Middleware
element that will eventually be produced upon dependency injection, and derives into a newMiddleware
- We start with a dependency
X
to calculate middlewareA
- We give a way for going from middleware
A
to middlewareB
- Our resulting mapped
MiddlewareReader
will accept dependencyX
to calculate middlewareB
Dependency type hasn’t changed at all
Declaration
Swift
public func mapMiddleware<NewMiddleware: MiddlewareProtocol>(_ transform: @escaping (MiddlewareType) -> NewMiddleware) -> MiddlewareReader<Dependencies, NewMiddleware>
Parameters
transform
function that transforms original produced Middleware into a new one, once the dependencies are injected
Return Value
a new
MiddlewareReader
that will create not the original MiddlewareType any more, but a NewMiddleware mapped from the original - We start with a dependency
-
contramapDependecies(_:
Extension method) Maps the
Dependencies
element, which is the input environment of the calculation for a particular middleware, using a contravariant function that will allow to lift this reader into aMiddlewareReader
compatible with a more global dependencies structure.Once this
MiddlewareReader
is lifted to depend onWorld
(where world means all dependencies you need for all middlewares), it can be combined with others that also depend on the sameWorld
, so this is useful for composition as you eventually want to combine all sorts of middlewares that have different dependencies, so this is for finding a common ground for all of them.- We start with a local dependency
X
to calculate middlewareA
- We give a way to extract depdendency
X
from worldW
(W
->X
), where world means all dependencies you need for all middlewares - Our resulting
MiddlewareReader
will accept dependencyW
to calculate middlewareA
Middleware type hasn’t changed at all
Declaration
Swift
public func contramapDependecies<World>(_ extractOnlyDependenciesNeededForThisMiddleware: @escaping (World) -> Dependencies) -> MiddlewareReader<World, MiddlewareType>
Parameters
extractOnlyDependenciesNeededForThisMiddleware
given all dependencies in the World of this app, that are needed for all middlewares and not only this one, extracts only what we need for this one
Return Value
a new
MiddlewareReader
that will require the fullWorld
to create theMiddlewareType
. It can be combined with others that also depend on the sameWorld
, so this is useful for composition as you eventually want to combine all sorts of middlewares that have different dependencies, so this is for finding a common ground for all of them. - We start with a local dependency
-
Maps the
Middleware
element that will eventually be produced upon dependency injection, and derives into a newMiddleware
Also maps the
Dependencies
element, which is the input environment of the calculation for a particular middleware, using a contravariant function that will allow to lift this reader into aMiddlewareReader
compatible with a more global dependencies structure.Once this
MiddlewareReader
is lifted to depend onWorld
(where world means all dependencies you need for all middlewares), it can be combined with others that also depend on the sameWorld
, so this is useful for composition as you eventually want to combine all sorts of middlewares that have different dependencies, so this is for finding a common ground for all of them.- We start with a dependency
X
to calculate middlewareA
- We give a way for going from middleware
A
to middlewareB
- We also give a way to extract depdendency
X
from worldW
(W
->X
), where world means all dependencies you need for all middlewares Our resulting mapped
MiddlewareReader
will accept dependency@
to calculate middlewareB
Declaration
Swift
public func dimap<NewMiddleware: MiddlewareProtocol, World>( transformMiddleware: @escaping (MiddlewareType) -> NewMiddleware, extractOnlyDependenciesNeededForThisMiddleware: @escaping (World) -> Dependencies ) -> MiddlewareReader<World, NewMiddleware>
Parameters
transformMiddleware
function that transforms original produced Middleware into a new one, once the dependencies are injected
extractOnlyDependenciesNeededForThisMiddleware
given all dependencies in the World of this app, that are needed for all middlewares and not only this one, extracts only what we need for this one
Return Value
a new
MiddlewareReader
that will require the fullWorld
to create not the original MiddlewareType any more, but a NewMiddleware mapped from the original. It can be combined with others that also depend on the sameWorld
, so this is useful for composition as you eventually want to combine all sorts of middlewares that have different dependencies, so this is for finding a common ground for all of them. - We start with a dependency
-
flatMap(_:
Extension method) Having a MiddlewareReader mapping that results in another MiddlewareReader that also depends on same environment, we can flatten up the map by using the same environment to inject in both MiddlewareReaders. Useful when there’s a chain of dependencies
Declaration
Swift
public func flatMap<NewMiddlewareReader: MiddlewareReaderProtocol>(_ transform: @escaping (MiddlewareType) -> NewMiddlewareReader) -> NewMiddlewareReader where NewMiddlewareReader.Dependencies == Dependencies
Parameters
transform
a function that, from the produced middleware of the original middleware reader, can create another middleware reader that produces a different middleware, as long as their dependencies are the same
Return Value
a flatten
MiddlewareReader
with transformation applied and dependencies injected in the original middleware reader, the produced middleware given to the transform function and injected again. -
pure(_:
Extension method) Wraps a pure function in a
MiddlewareReader
container just for the sake of composition. Nothing is actually needed for the calculation and injected dependency will be ignored. This is useful for lifting aMiddleware
into aMiddlewareReader
, so you can compose with other MiddlewareReaders that actually depend on dependencies.Declaration
Swift
public static func pure(_ value: MiddlewareType) -> Self
Parameters
value
The middleware that will be eventually returned when “inject” is called. This is a autoclosure so it can be lazily evaluated.
Return Value
a
MiddlewareReader
that wraps the given Middleware untilinject
is called. -
zip(_:
Extension method_: with: ) Creates a MiddlewareReader that combines multiple readers into one, as long as they depend on same environment. Once this environment is injected, upstream readers will run and the result will be a tuple containing the resulting values of each upstream reader. Then you provide a way to combine there resulting Middlewares into one.
Declaration
Swift
public static func zip<M1: MiddlewareReaderProtocol, M2: MiddlewareReaderProtocol, MOutput: MiddlewareProtocol>( _ reader1: M1, _ reader2: M2, with map: @escaping (M1.MiddlewareType, M2.MiddlewareType) -> MOutput ) -> MiddlewareReader<M1.Dependencies, MOutput> where M1.Dependencies == M2.Dependencies
Parameters
reader1
first reader type
reader2
second reader type
map
how to combine produced middlewares into a single one, of type
MOutput
Return Value
middleware reader that gives a middleware of type
MOutput
after receiving the injected dependencies -
zip(_:
Extension method_: _: with: ) Creates a MiddlewareReader that combines multiple readers into one, as long as they depend on same environment. Once this environment is injected, upstream readers will run and the result will be a tuple containing the resulting values of each upstream reader. Then you provide a way to combine there resulting Middlewares into one.
Declaration
Swift
public static func zip<M1: MiddlewareReaderProtocol, M2: MiddlewareReaderProtocol, M3: MiddlewareReaderProtocol, MOutput: MiddlewareProtocol>( _ reader1: M1, _ reader2: M2, _ reader3: M3, with map: @escaping (M1.MiddlewareType, M2.MiddlewareType, M3.MiddlewareType) -> MOutput ) -> MiddlewareReader<M1.Dependencies, MOutput> where M1.Dependencies == M2.Dependencies, M1.Dependencies == M3.Dependencies
Parameters
reader1
first reader type
reader2
second reader type
reader3
third reader type
map
how to combine produced middlewares into a single one, of type
MOutput
Return Value
middleware reader that gives a middleware of type
MOutput
after receiving the injected dependencies -
zip(_:
Extension method_: _: _: with: ) Creates a MiddlewareReader that combines multiple readers into one, as long as they depend on same environment. Once this environment is injected, upstream readers will run and the result will be a tuple containing the resulting values of each upstream reader. Then you provide a way to combine there resulting Middlewares into one.
Declaration
Swift
public static func zip< M1: MiddlewareReaderProtocol, M2: MiddlewareReaderProtocol, M3: MiddlewareReaderProtocol, M4: MiddlewareReaderProtocol, MOutput: MiddlewareProtocol > ( _ reader1: M1, _ reader2: M2, _ reader3: M3, _ reader4: M4, with map: @escaping (M1.MiddlewareType, M2.MiddlewareType, M3.MiddlewareType, M4.MiddlewareType) -> MOutput ) -> MiddlewareReader<M1.Dependencies, MOutput> where M1.Dependencies == M2.Dependencies, M1.Dependencies == M3.Dependencies, M1.Dependencies == M4.Dependencies
Parameters
reader1
first reader type
reader2
second reader type
reader3
third reader type
reader4
fourth reader type
map
how to combine produced middlewares into a single one, of type
MOutput
Return Value
middleware reader that gives a middleware of type
MOutput
after receiving the injected dependencies -
zip(_:
Extension method_: _: _: _: with: ) Creates a MiddlewareReader that combines multiple readers into one, as long as they depend on same environment. Once this environment is injected, upstream readers will run and the result will be a tuple containing the resulting values of each upstream reader. Then you provide a way to combine there resulting Middlewares into one.
Declaration
Swift
public static func zip< M1: MiddlewareReaderProtocol, M2: MiddlewareReaderProtocol, M3: MiddlewareReaderProtocol, M4: MiddlewareReaderProtocol, M5: MiddlewareReaderProtocol, MOutput: MiddlewareProtocol > ( _ reader1: M1, _ reader2: M2, _ reader3: M3, _ reader4: M4, _ reader5: M5, with map: @escaping (M1.MiddlewareType, M2.MiddlewareType, M3.MiddlewareType, M4.MiddlewareType, M5.MiddlewareType) -> MOutput ) -> MiddlewareReader<M1.Dependencies, MOutput> where M1.Dependencies == M2.Dependencies, M1.Dependencies == M3.Dependencies, M1.Dependencies == M4.Dependencies, M1.Dependencies == M5.Dependencies
Parameters
reader1
first reader type
reader2
second reader type
reader3
third reader type
reader4
fourth reader type
reader5
fifth reader type
map
how to combine produced middlewares into a single one, of type
MOutput
Return Value
middleware reader that gives a middleware of type
MOutput
after receiving the injected dependencies -
zip(_:
Extension method_: _: _: _: _: with: ) Creates a MiddlewareReader that combines multiple readers into one, as long as they depend on same environment. Once this environment is injected, upstream readers will run and the result will be a tuple containing the resulting values of each upstream reader. Then you provide a way to combine there resulting Middlewares into one.
Declaration
Swift
public static func zip< M1: MiddlewareReaderProtocol, M2: MiddlewareReaderProtocol, M3: MiddlewareReaderProtocol, M4: MiddlewareReaderProtocol, M5: MiddlewareReaderProtocol, M6: MiddlewareReaderProtocol, MOutput: MiddlewareProtocol > ( _ reader1: M1, _ reader2: M2, _ reader3: M3, _ reader4: M4, _ reader5: M5, _ reader6: M6, with map: @escaping ( M1.MiddlewareType, M2.MiddlewareType, M3.MiddlewareType, M4.MiddlewareType, M5.MiddlewareType, M6.MiddlewareType ) -> MOutput ) -> MiddlewareReader<M1.Dependencies, MOutput> where M1.Dependencies == M2.Dependencies, M1.Dependencies == M3.Dependencies, M1.Dependencies == M4.Dependencies, M1.Dependencies == M5.Dependencies, M1.Dependencies == M6.Dependencies
Parameters
reader1
first reader type
reader2
second reader type
reader3
third reader type
reader4
fourth reader type
reader5
fifth reader type
reader6
sixth reader type
map
how to combine produced middlewares into a single one, of type
MOutput
Return Value
middleware reader that gives a middleware of type
MOutput
after receiving the injected dependencies -
zip(_:
Extension method_: _: _: _: _: _: with: ) Creates a MiddlewareReader that combines multiple readers into one, as long as they depend on same environment. Once this environment is injected, upstream readers will run and the result will be a tuple containing the resulting values of each upstream reader. Then you provide a way to combine there resulting Middlewares into one.
Declaration
Swift
public static func zip< M1: MiddlewareReaderProtocol, M2: MiddlewareReaderProtocol, M3: MiddlewareReaderProtocol, M4: MiddlewareReaderProtocol, M5: MiddlewareReaderProtocol, M6: MiddlewareReaderProtocol, M7: MiddlewareReaderProtocol, MOutput: MiddlewareProtocol > ( _ reader1: M1, _ reader2: M2, _ reader3: M3, _ reader4: M4, _ reader5: M5, _ reader6: M6, _ reader7: M7, with map: @escaping ( M1.MiddlewareType, M2.MiddlewareType, M3.MiddlewareType, M4.MiddlewareType, M5.MiddlewareType, M6.MiddlewareType, M7.MiddlewareType ) -> MOutput ) -> MiddlewareReader<M1.Dependencies, MOutput> where M1.Dependencies == M2.Dependencies, M1.Dependencies == M3.Dependencies, M1.Dependencies == M4.Dependencies, M1.Dependencies == M5.Dependencies, M1.Dependencies == M6.Dependencies, M1.Dependencies == M7.Dependencies
Parameters
reader1
first reader type
reader2
second reader type
reader3
third reader type
reader4
fourth reader type
reader5
fifth reader type
reader6
sixth reader type
reader7
seventh reader type
map
how to combine produced middlewares into a single one, of type
MOutput
Return Value
middleware reader that gives a middleware of type
MOutput
after receiving the injected dependencies -
zip(_:
Extension method_: _: _: _: _: _: _: with: ) Creates a MiddlewareReader that combines multiple readers into one, as long as they depend on same environment. Once this environment is injected, upstream readers will run and the result will be a tuple containing the resulting values of each upstream reader. Then you provide a way to combine there resulting Middlewares into one.
Declaration
Swift
public static func zip< M1: MiddlewareReaderProtocol, M2: MiddlewareReaderProtocol, M3: MiddlewareReaderProtocol, M4: MiddlewareReaderProtocol, M5: MiddlewareReaderProtocol, M6: MiddlewareReaderProtocol, M7: MiddlewareReaderProtocol, M8: MiddlewareReaderProtocol, MOutput: MiddlewareProtocol > ( _ reader1: M1, _ reader2: M2, _ reader3: M3, _ reader4: M4, _ reader5: M5, _ reader6: M6, _ reader7: M7, _ reader8: M8, with map: @escaping ( M1.MiddlewareType, M2.MiddlewareType, M3.MiddlewareType, M4.MiddlewareType, M5.MiddlewareType, M6.MiddlewareType, M7.MiddlewareType, M8.MiddlewareType ) -> MOutput ) -> MiddlewareReader<M1.Dependencies, MOutput> where M1.Dependencies == M2.Dependencies, M1.Dependencies == M3.Dependencies, M1.Dependencies == M4.Dependencies, M1.Dependencies == M5.Dependencies, M1.Dependencies == M6.Dependencies, M1.Dependencies == M7.Dependencies, M1.Dependencies == M8.Dependencies
Parameters
reader1
first reader type
reader2
second reader type
reader3
third reader type
reader4
fourth reader type
reader5
fifth reader type
reader6
sixth reader type
reader7
seventh reader type
reader8
eighth reader type
map
how to combine produced middlewares into a single one, of type
MOutput
Return Value
middleware reader that gives a middleware of type
MOutput
after receiving the injected dependencies -
zip(_:
Extension method_: _: _: _: _: _: _: _: with: ) Creates a MiddlewareReader that combines multiple readers into one, as long as they depend on same environment. Once this environment is injected, upstream readers will run and the result will be a tuple containing the resulting values of each upstream reader. Then you provide a way to combine there resulting Middlewares into one.
Declaration
Swift
public static func zip< M1: MiddlewareReaderProtocol, M2: MiddlewareReaderProtocol, M3: MiddlewareReaderProtocol, M4: MiddlewareReaderProtocol, M5: MiddlewareReaderProtocol, M6: MiddlewareReaderProtocol, M7: MiddlewareReaderProtocol, M8: MiddlewareReaderProtocol, M9: MiddlewareReaderProtocol, MOutput: MiddlewareProtocol > ( _ reader1: M1, _ reader2: M2, _ reader3: M3, _ reader4: M4, _ reader5: M5, _ reader6: M6, _ reader7: M7, _ reader8: M8, _ reader9: M9, with map: @escaping ( M1.MiddlewareType, M2.MiddlewareType, M3.MiddlewareType, M4.MiddlewareType, M5.MiddlewareType, M6.MiddlewareType, M7.MiddlewareType, M8.MiddlewareType, M9.MiddlewareType ) -> MOutput ) -> MiddlewareReader<M1.Dependencies, MOutput> where M1.Dependencies == M2.Dependencies, M1.Dependencies == M3.Dependencies, M1.Dependencies == M4.Dependencies, M1.Dependencies == M5.Dependencies, M1.Dependencies == M6.Dependencies, M1.Dependencies == M7.Dependencies, M1.Dependencies == M8.Dependencies, M1.Dependencies == M9.Dependencies
Parameters
reader1
first reader type
reader2
second reader type
reader3
third reader type
reader4
fourth reader type
reader5
fifth reader type
reader6
sixth reader type
reader7
seventh reader type
reader8
eighth reader type
reader9
ninth reader type
map
how to combine produced middlewares into a single one, of type
MOutput
Return Value
middleware reader that gives a middleware of type
MOutput
after receiving the injected dependencies -
zip(_:
Extension method_: _: _: _: _: _: _: _: _: with: ) Creates a MiddlewareReader that combines multiple readers into one, as long as they depend on same environment. Once this environment is injected, upstream readers will run and the result will be a tuple containing the resulting values of each upstream reader. Then you provide a way to combine there resulting Middlewares into one.
Declaration
Swift
public static func zip< M1: MiddlewareReaderProtocol, M2: MiddlewareReaderProtocol, M3: MiddlewareReaderProtocol, M4: MiddlewareReaderProtocol, M5: MiddlewareReaderProtocol, M6: MiddlewareReaderProtocol, M7: MiddlewareReaderProtocol, M8: MiddlewareReaderProtocol, M9: MiddlewareReaderProtocol, M10: MiddlewareReaderProtocol, MOutput: MiddlewareProtocol > ( _ reader1: M1, _ reader2: M2, _ reader3: M3, _ reader4: M4, _ reader5: M5, _ reader6: M6, _ reader7: M7, _ reader8: M8, _ reader9: M9, _ reader10: M10, with map: @escaping ( M1.MiddlewareType, M2.MiddlewareType, M3.MiddlewareType, M4.MiddlewareType, M5.MiddlewareType, M6.MiddlewareType, M7.MiddlewareType, M8.MiddlewareType, M9.MiddlewareType, M10.MiddlewareType ) -> MOutput ) -> MiddlewareReader<M1.Dependencies, MOutput> where M1.Dependencies == M2.Dependencies, M1.Dependencies == M3.Dependencies, M1.Dependencies == M4.Dependencies, M1.Dependencies == M5.Dependencies, M1.Dependencies == M6.Dependencies, M1.Dependencies == M7.Dependencies, M1.Dependencies == M8.Dependencies, M1.Dependencies == M9.Dependencies, M1.Dependencies == M10.Dependencies
Parameters
reader1
first reader type
reader2
second reader type
reader3
third reader type
reader4
fourth reader type
reader5
fifth reader type
reader6
sixth reader type
reader7
seventh reader type
reader8
eighth reader type
reader9
ninth reader type
reader10
tenth reader type
map
how to combine produced middlewares into a single one, of type
MOutput
Return Value
middleware reader that gives a middleware of type
MOutput
after receiving the injected dependencies
-
<>(_:
Extension method_: ) Compose two Semigroup Middlewares into one, before even materializing them into real instances.
Declaration
Swift
public static func <> (lhs: Self, rhs: Self) -> Self
Parameters
lhs
middleware reader that will generate a middleware which runs first
rhs
middleware reader that will generate a middleware which runs last
Return Value
a composed Middleware Reader that, once injected with dependencies, will produce a middleware that runs first the left and then the right middleware
-
identity
Extension methodAn identity MiddlewareReader ignores whatever Dependencies are given and simply return an identity Middleware. Composing any given middleware reader “A” with the identity middleware reader will be exactly the same as composing in the other order and also exactly the same as only the middleware reader “A” alone, which means, it doesn’t change anything in the MiddlewareReader “A” or its resulting Middleware, regardless of the order it was composed to.
Declaration
Swift
public static var identity: Self { get }