├── .gitignore ├── .npmrc ├── .yarnrc ├── LICENSE ├── README.md ├── bower.json ├── package.json ├── src └── React │ ├── Redux.js │ ├── Redux.purs │ └── Redux │ ├── Internal.purs │ ├── Middleware.purs │ ├── Reducer.purs │ └── Types.purs └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .psci 3 | .psci_modules 4 | .pulp-cache/ 5 | .psc-ide-port 6 | npm-debug.log 7 | node_modules/ 8 | bower_components/ 9 | tmp/ 10 | output/ 11 | yarn-error.log 12 | *.tix 13 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | tag-version-prefix=v 2 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | version-tag-prefix "v" 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2017 Eric Thul 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the 5 | "Software"), in the Software without restriction, including without 6 | limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to 8 | whom the Software is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # purescript-react-redux 2 | 3 | A library for using [Redux with React](http://redux.js.org/docs/basics/UsageWithReact.html). 4 | 5 | ## Installation 6 | 7 | ```bash 8 | bower install --save purescript-react-redux 9 | ``` 10 | 11 | ## Example 12 | 13 | Refer to the [purescript-react-redux-example](https://github.com/ethul/purescript-react-redux-example) for an example. 14 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "purescript-react-redux", 3 | "description": "PureScript library for using Redux with React", 4 | "keywords": [ 5 | "purescript", 6 | "react", 7 | "redux" 8 | ], 9 | "license": "MIT", 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/ethul/purescript-react-redux.git" 13 | }, 14 | "ignore": [ 15 | "*", 16 | "!src/**/*" 17 | ], 18 | "dependencies": { 19 | "purescript-react": "^3.0.0", 20 | "purescript-monoid": "^3.1.0", 21 | "purescript-strings": "^3.3.1", 22 | "purescript-nullable": "^3.0.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "purescript-react-redux", 3 | "version": "6.1.0", 4 | "private": true, 5 | "files": [], 6 | "scripts": { 7 | "purs:compile": "purs compile 'src/**/*.purs' 'test/**/*.purs' 'bower_components/purescript-*/src/**/*.purs' 2>&1", 8 | "pscid": "pscid" 9 | }, 10 | "devDependencies": {} 11 | } 12 | -------------------------------------------------------------------------------- /src/React/Redux.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Redux = require('redux'); 4 | 5 | var ReactRedux = require('react-redux'); 6 | 7 | exports.reduxCreateStore = function reduxCreateStore(reducer, state, enhancer){ 8 | return Redux.createStore(reducer, state, enhancer); 9 | }; 10 | 11 | exports.reduxApplyMiddleware = function reduxApplyMiddleware(middleware){ 12 | return Redux.applyMiddleware.apply(Redux, middleware); 13 | }; 14 | 15 | exports.reduxConnect = function reduxConnect(mapStateToProps, mapDispatchToProps, mergeProps, options){ 16 | return ReactRedux.connect(mapStateToProps, mapDispatchToProps, mergeProps, options); 17 | }; 18 | 19 | exports.reduxConnect_ = exports.reduxConnect; 20 | 21 | exports.reduxProviderClass = ReactRedux.Provider; 22 | 23 | exports.unsafeMerge = function unsafeMerge(l) { 24 | return function (r) { 25 | var o = {}; 26 | return Object.assign(o, l, r); 27 | }; 28 | }; 29 | -------------------------------------------------------------------------------- /src/React/Redux.purs: -------------------------------------------------------------------------------- 1 | module React.Redux 2 | ( ConnectClass 3 | , ConnectClass' 4 | , ConnectOptions 5 | , connect 6 | , connect_ 7 | , createElement 8 | , createElement_ 9 | , createProviderElement 10 | , createStore 11 | , createStore' 12 | , applyMiddleware 13 | , module Redux 14 | ) where 15 | 16 | import Prelude 17 | 18 | import Control.Monad.Eff (Eff, kind Effect) 19 | import Control.Monad.Eff.Uncurried (EffFn3, runEffFn3) 20 | 21 | import Data.Function.Uncurried (Fn2, Fn3, Fn4, mkFn2, mkFn3, runFn4) 22 | 23 | import Unsafe.Coerce (unsafeCoerce) 24 | 25 | import React as React 26 | import React.Redux.Internal as Internal 27 | import React.Redux.Middleware (Middleware, MiddlewareAPI) as Redux 28 | import React.Redux.Reducer (reducerFlipped) as Redux 29 | import React.Redux.Types 30 | ( REDUX 31 | , ReduxEffect 32 | , Reducer 33 | , BaseDispatch 34 | , Dispatch 35 | , ReduxAction 36 | , ReduxAction' 37 | , ReduxReducer 38 | , ReduxBaseDispatch 39 | , ReduxDispatch 40 | , ReduxMiddlewareAPI 41 | , ReduxMiddleware 42 | , ReduxStoreCreator 43 | , ReduxStoreEnhancer 44 | , ReduxStore 45 | ) as Redux 46 | 47 | -- | Connected class representation parameterized by `state`, `ownProps`, `props`, and `action`. 48 | foreign import data ConnectClass :: Type -> Type -> Type -> Type -> Type 49 | 50 | -- | Connect class type alias for a class with no `ownProps`. 51 | type ConnectClass' state props action = ConnectClass state { } props action 52 | 53 | -- | Options that can be passed on calling `connect`. Additional options may also be provided as needed. 54 | type ConnectOptions state stateProps ownProps props options 55 | = ( pure :: Boolean 56 | , areStatesEqual :: Fn2 (Record state) (Record state) Boolean 57 | , areOwnPropsEqual :: Fn2 (Record ownProps) (Record ownProps) Boolean 58 | , areStatePropsEqual :: Fn2 (Record stateProps) (Record stateProps) Boolean 59 | , areMergedPropsEqual :: Fn2 (Record props) (Record props) Boolean 60 | , storeKey :: String 61 | | options 62 | ) 63 | 64 | -- | Redux connect function that depends on `ownProps`. 65 | -- | 66 | -- | Redux will invoke the mapping functions whenever the connected 67 | -- | class receives updated `ownProps`. 68 | connect 69 | :: forall eff state action stateProps dispatchProps ownProps stateDispatchProps props options options' options'' 70 | . Union stateProps dispatchProps stateDispatchProps 71 | => Union stateDispatchProps ownProps props 72 | => Union options options'' (ConnectOptions state stateProps ownProps props options') 73 | => (Record state -> Record ownProps -> Record stateProps) 74 | -> (Redux.BaseDispatch eff action -> Record ownProps -> Record dispatchProps) 75 | -> Record options 76 | -> React.ReactClass (Record props) 77 | -> ConnectClass (Record state) (Record ownProps) (Record props) action 78 | connect stateToProps dispatchToProps options = 79 | runFn4 reduxConnect 80 | (mkFn2 stateToProps) 81 | (mkFn2 (dispatchToProps <<< Internal.reduxDispatchToDispatch)) 82 | (mkFn3 mergeProps) 83 | options 84 | 85 | -- | Redux connect function that does not depend on `ownProps`. 86 | connect_ 87 | :: forall eff state action stateProps dispatchProps props options options' options'' 88 | . Union stateProps dispatchProps props 89 | => Union props () props 90 | => Union options options'' (ConnectOptions state stateProps () props options') 91 | => (Record state -> Record stateProps) 92 | -> (Redux.BaseDispatch eff action -> Record dispatchProps) 93 | -> Record options 94 | -> React.ReactClass (Record props) 95 | -> ConnectClass' (Record state) (Record props) action 96 | connect_ stateToProps dispatchToProps options = 97 | runFn4 reduxConnect_ 98 | stateToProps 99 | (dispatchToProps <<< Internal.reduxDispatchToDispatch) 100 | (mkFn3 mergeProps) 101 | options 102 | 103 | mergeProps 104 | :: forall stateProps dispatchProps ownProps stateDispatchProps props 105 | . Union stateProps dispatchProps stateDispatchProps 106 | => Union stateDispatchProps ownProps props 107 | => Record stateProps 108 | -> Record dispatchProps 109 | -> Record ownProps 110 | -> Record props 111 | mergeProps stateProps dispatchProps ownProps = unionMerge ownProps (unionMerge dispatchProps stateProps) 112 | 113 | createElement 114 | :: forall state ownProps props action 115 | . ConnectClass (Record state) (Record ownProps) (Record props) action 116 | -> Record ownProps 117 | -> Array React.ReactElement 118 | -> React.ReactElement 119 | createElement reduxClass = 120 | React.createElement reactClass 121 | where 122 | reactClass :: React.ReactClass (Record ownProps) 123 | reactClass = unsafeCoerce reduxClass 124 | 125 | createElement_ 126 | :: forall state props action 127 | . ConnectClass' (Record state) (Record props) action 128 | -> Array React.ReactElement 129 | -> React.ReactElement 130 | createElement_ reduxClass = createElement reduxClass { } 131 | 132 | createProviderElement 133 | :: forall eff state action 134 | . Redux.ReduxStore eff state action 135 | -> Array React.ReactElement 136 | -> React.ReactElement 137 | createProviderElement store = React.createElement reduxProviderClass { store } 138 | 139 | applyMiddleware 140 | :: forall eff state action result 141 | . Array (Redux.Middleware eff state action action result) 142 | -> Redux.ReduxStoreEnhancer eff state action 143 | applyMiddleware = reduxApplyMiddleware <<< map Internal.middlewareToReduxMiddleware 144 | 145 | createStore 146 | :: forall eff state action 147 | . Redux.Reducer action state 148 | -> state 149 | -> Redux.ReduxStoreEnhancer eff state action 150 | -> Eff (Redux.ReduxEffect eff) (Redux.ReduxStore eff state action) 151 | createStore reducer = runEffFn3 reduxCreateStore (Internal.reducerToReduxReducer reducer) 152 | 153 | createStore' 154 | :: forall eff state action 155 | . Redux.Reducer action state 156 | -> state 157 | -> Eff (Redux.ReduxEffect eff) (Redux.ReduxStore eff state action) 158 | createStore' reducer state = createStore reducer state id 159 | 160 | foreign import reduxApplyMiddleware 161 | :: forall eff state action a b 162 | . Array (Redux.ReduxMiddleware eff state action a b) 163 | -> Redux.ReduxStoreEnhancer eff state action 164 | 165 | foreign import reduxCreateStore 166 | :: forall eff state action 167 | . EffFn3 (Redux.ReduxEffect eff) 168 | (Redux.ReduxReducer state action) 169 | state 170 | (Redux.ReduxStoreEnhancer eff state action) 171 | (Redux.ReduxStore eff state action) 172 | 173 | foreign import reduxProviderClass 174 | :: forall eff state action 175 | . React.ReactClass { store :: Redux.ReduxStore eff state action } 176 | 177 | foreign import reduxConnect 178 | :: forall eff state action stateProps dispatchProps ownProps props options 179 | . Fn4 (Fn2 (Record state) (Record ownProps) (Record stateProps)) 180 | (Fn2 (Redux.ReduxDispatch eff action action) (Record ownProps) (Record dispatchProps)) 181 | (Fn3 (Record stateProps) (Record dispatchProps) (Record ownProps) (Record props)) 182 | (Record options) 183 | (React.ReactClass (Record props) -> ConnectClass (Record state) (Record ownProps) (Record props) action) 184 | 185 | foreign import reduxConnect_ 186 | :: forall eff state action stateProps dispatchProps props options 187 | . Fn4 (Record state -> Record stateProps) 188 | (Redux.ReduxDispatch eff action action -> Record dispatchProps) 189 | (Fn3 (Record stateProps) (Record dispatchProps) { } (Record props)) 190 | (Record options) 191 | (React.ReactClass (Record props) -> ConnectClass' (Record state) (Record props) action) 192 | 193 | -- | Temporarily including `unionMerge` to publish to Pursuit. 194 | -- | See purescript/purescript-record#7 195 | -- | 196 | unionMerge :: forall l r u. Union r l u => Record l -> Record r -> Record u 197 | unionMerge = unsafeMerge 198 | 199 | foreign import unsafeMerge 200 | :: forall l r u 201 | . Record l 202 | -> Record r 203 | -> Record u 204 | -------------------------------------------------------------------------------- /src/React/Redux/Internal.purs: -------------------------------------------------------------------------------- 1 | module React.Redux.Internal where 2 | 3 | import Prelude 4 | 5 | import Control.Monad.Eff.Uncurried (mkEffFn1, runEffFn1) 6 | 7 | import Data.Function.Uncurried (mkFn2, runFn2) 8 | import Data.Maybe (Maybe, fromMaybe, maybe) 9 | import Data.Newtype (wrap, unwrap) 10 | import Data.Nullable (Nullable, toMaybe, toNullable) 11 | 12 | import Unsafe.Coerce (unsafeCoerce) 13 | 14 | import React.Redux.Middleware (Middleware, MiddlewareAPI) 15 | 16 | import React.Redux.Types 17 | ( BaseDispatch 18 | , Dispatch 19 | , Reducer 20 | , ReduxAction' 21 | , ReduxReducer 22 | , ReduxBaseDispatch 23 | , ReduxDispatch 24 | , ReduxMiddlewareAPI 25 | , ReduxMiddleware 26 | ) 27 | 28 | reduxActionType :: String 29 | reduxActionType = "@@PURESCRIPT_REACT_REDUX" 30 | 31 | reduxActionToAction :: forall action. ReduxAction' action -> action 32 | reduxActionToAction { action } = action 33 | 34 | actionToReduxAction :: forall action. action -> ReduxAction' action 35 | actionToReduxAction action = 36 | { type: reduxActionType <> "/" <> suffix 37 | , action 38 | } 39 | where 40 | constructor :: Maybe { name :: Nullable String} 41 | constructor = toMaybe (unsafeCoerce action).constructor 42 | 43 | suffix :: String 44 | suffix = fromMaybe "UnknownConstructorName" (constructor >>= \a -> toMaybe a.name) 45 | 46 | reduxReducerToReducer :: forall state action. ReduxReducer state action -> Reducer action state 47 | reduxReducerToReducer reduxReducer = wrap (flip (runFn2 reduxReducer) <<< actionToReduxAction <<< toNullable <<< pure) 48 | 49 | reducerToReduxReducer :: forall state action. Reducer action state -> ReduxReducer state action 50 | reducerToReduxReducer reducer = mkFn2 \state -> maybe state (flip (unwrap reducer) state) <<< toMaybe <<< reduxActionToAction 51 | 52 | reduxBaseDispatchToBaseDispatch :: forall eff action. ReduxBaseDispatch eff action -> BaseDispatch eff action 53 | reduxBaseDispatchToBaseDispatch = (>>>) actionToReduxAction <<< (<<<) (map reduxActionToAction) <<< runEffFn1 54 | 55 | reduxDispatchToDispatch :: forall eff action result. ReduxDispatch eff action result -> Dispatch eff action result 56 | reduxDispatchToDispatch = (>>>) actionToReduxAction <<< runEffFn1 57 | 58 | baseDispatchToReduxBaseDispatch :: forall eff action. Dispatch eff action action -> ReduxBaseDispatch eff action 59 | baseDispatchToReduxBaseDispatch = mkEffFn1 <<< (>>>) reduxActionToAction <<< (<<<) (map actionToReduxAction) 60 | 61 | dispatchToReduxDispatch :: forall eff action result. Dispatch eff action result -> ReduxDispatch eff action result 62 | dispatchToReduxDispatch = mkEffFn1 <<< (>>>) reduxActionToAction 63 | 64 | reduxMiddlewareApiToMiddlewareApi :: forall eff state action. ReduxMiddlewareAPI eff state action -> MiddlewareAPI eff state action 65 | reduxMiddlewareApiToMiddlewareApi { getState, dispatch } = { getState, dispatch: reduxBaseDispatchToBaseDispatch dispatch } 66 | 67 | middlewareApiToReduxMiddlewareApi :: forall eff state action. MiddlewareAPI eff state action -> ReduxMiddlewareAPI eff state action 68 | middlewareApiToReduxMiddlewareApi { getState, dispatch } = { getState, dispatch: baseDispatchToReduxBaseDispatch dispatch } 69 | 70 | reduxMiddlewareToMiddleware :: forall eff state action a b. ReduxMiddleware eff state action a b -> Middleware eff state action a b 71 | reduxMiddlewareToMiddleware reduxMiddleware = wrap $ \middlewareApi dispatch -> reduxDispatchToDispatch (reduxMiddleware (middlewareApiToReduxMiddlewareApi middlewareApi) (dispatchToReduxDispatch dispatch)) 72 | 73 | middlewareToReduxMiddleware :: forall eff state action a b. Middleware eff state action a b -> ReduxMiddleware eff state action a b 74 | middlewareToReduxMiddleware middleware reduxMiddlewareApi = reduxMiddleware 75 | where 76 | middleware' :: Dispatch eff action a -> Dispatch eff action b 77 | middleware' = unwrap middleware (reduxMiddlewareApiToMiddlewareApi reduxMiddlewareApi) 78 | 79 | reduxMiddleware :: ReduxDispatch eff action a -> ReduxDispatch eff action b 80 | reduxMiddleware = dispatchToReduxDispatch <<< middleware' <<< reduxDispatchToDispatch 81 | -------------------------------------------------------------------------------- /src/React/Redux/Middleware.purs: -------------------------------------------------------------------------------- 1 | module React.Redux.Middleware where 2 | 3 | import Prelude 4 | 5 | import Control.Monad.Eff (Eff) 6 | 7 | import Data.Monoid (class Monoid, mempty) 8 | import Data.Newtype (class Newtype, unwrap) 9 | 10 | import React.Redux.Types (ReduxEffect, Dispatch) 11 | 12 | type MiddlewareAPI eff state action 13 | = { getState :: Eff (ReduxEffect eff) state 14 | , dispatch :: Dispatch eff action action 15 | } 16 | 17 | newtype Middleware eff state action a b = Middleware (MiddlewareAPI eff state action -> Dispatch eff action a -> Dispatch eff action b) 18 | 19 | derive instance newtypeMiddleware :: Newtype (Middleware eff state action a b) _ 20 | 21 | instance semigroupoidMiddleware :: Semigroupoid (Middleware eff state action) where 22 | compose (Middleware f) (Middleware g) = Middleware (\api -> f api <<< g api) 23 | 24 | instance categoryMiddleware :: Category (Middleware eff state action) where 25 | id = Middleware (const id) 26 | 27 | instance functorMiddleware :: Functor (Middleware eff state action a) where 28 | map f (Middleware g) = Middleware (\api next action -> f <$> g api next action) 29 | 30 | instance applyMiddleware :: Apply (Middleware eff state action a) where 31 | apply (Middleware f) (Middleware g) = 32 | Middleware $ \api next action -> do 33 | a <- g api next action 34 | 35 | k <- f api next action 36 | 37 | pure (k a) 38 | 39 | instance applicativeMiddleware :: Applicative (Middleware eff state action a) where 40 | pure a = Middleware (\_ _ _ -> pure a) 41 | 42 | instance bindMiddleware :: Bind (Middleware eff state action a) where 43 | bind (Middleware m) f = 44 | Middleware $ \api next action -> do 45 | a <- m api next action 46 | 47 | unwrap (f a) api next action 48 | 49 | instance monadMiddleware :: Monad (Middleware eff state action a) 50 | 51 | instance semigroupMiddleware :: Semigroup b => Semigroup (Middleware eff state action a b) where 52 | append (Middleware f) (Middleware g) = 53 | Middleware $ \api next action -> do 54 | b1 <- f api next action 55 | 56 | b2 <- g api next action 57 | 58 | pure (b1 <> b2) 59 | 60 | instance monoidMiddleware :: Monoid b => Monoid (Middleware eff state action a b) where 61 | mempty = Middleware (const (const (const (pure mempty)))) 62 | -------------------------------------------------------------------------------- /src/React/Redux/Reducer.purs: -------------------------------------------------------------------------------- 1 | module React.Redux.Reducer where 2 | 3 | import Prelude 4 | 5 | import Data.Monoid (class Monoid, mempty) 6 | import Data.Newtype (class Newtype, wrap, unwrap) 7 | 8 | newtype Reducer action state state' = Reducer (action -> state -> state') 9 | 10 | derive instance newtypeReducer :: Newtype (Reducer action state state') _ 11 | 12 | instance semigroupoidReducer :: Semigroupoid (Reducer action) where 13 | compose (Reducer f) (Reducer g) = Reducer (\action -> f action <<< g action) 14 | 15 | instance categoryReducer :: Category (Reducer action) where 16 | id = Reducer (const id) 17 | 18 | instance functorReducer :: Functor (Reducer action state) where 19 | map f (Reducer g) = Reducer ((<<<) f <<< g) 20 | 21 | instance applyReducer :: Apply (Reducer action state) where 22 | apply (Reducer f) (Reducer g) = Reducer (\action state -> (f action) state (g action state)) 23 | 24 | instance applicativeReducer :: Applicative (Reducer action state) where 25 | pure a = Reducer (\_ _ -> a) 26 | 27 | instance bindReducer :: Bind (Reducer action state) where 28 | bind (Reducer m) f = Reducer (\action state -> unwrap (f (m action state)) action state) 29 | 30 | instance monadReducer :: Monad (Reducer action state) 31 | 32 | instance semigroupReducer :: Semigroup state' => Semigroup (Reducer action state state') where 33 | append (Reducer f) (Reducer g) = Reducer (\action state -> f action state <> g action state) 34 | 35 | instance monoidReducer :: Monoid state' => Monoid (Reducer action state state') where 36 | mempty = Reducer (const (const (mempty))) 37 | 38 | reducerFlipped :: forall action state state'. (state -> action -> state') -> Reducer action state state' 39 | reducerFlipped = wrap <<< flip 40 | -------------------------------------------------------------------------------- /src/React/Redux/Types.purs: -------------------------------------------------------------------------------- 1 | module React.Redux.Types where 2 | 3 | import Prelude 4 | 5 | import Control.Monad.Eff (kind Effect, Eff) 6 | import Control.Monad.Eff.Uncurried (EffFn1) 7 | 8 | import Data.Function.Uncurried (Fn2) 9 | import Data.Nullable (Nullable) 10 | 11 | import React.Redux.Reducer as Reducer 12 | 13 | -- | Effect type for Redux. 14 | foreign import data REDUX :: Effect 15 | 16 | -- | Convenience type alias for the Redux effect. 17 | type ReduxEffect eff = (redux :: REDUX | eff) 18 | 19 | -- | Reducer that does not change the type of the `state`. 20 | type Reducer action state = Reducer.Reducer action state state 21 | 22 | -- | Dispatching function that returns the action it was passed. 23 | type BaseDispatch eff action = Dispatch eff action action 24 | 25 | -- | Dispatching function that returns a `result` type given an action. 26 | type Dispatch eff action result = action -> Eff (ReduxEffect eff) result 27 | 28 | -- | Redux actions must be a record with a `type` field. 29 | type ReduxAction r = { type :: String | r } 30 | 31 | -- | Convenience type for converting an `action` in this module to a `ReduxAction`. 32 | type ReduxAction' action = ReduxAction (action :: action) 33 | 34 | -- | Reducing function that takes a `state` and `ReduxAction` and returns a `state`. 35 | type ReduxReducer state action = Fn2 state (ReduxAction' (Nullable action)) state 36 | 37 | -- | The `ReduxBaseDispatch` is the dispatching function provided to the store without any middleware. 38 | type ReduxBaseDispatch eff action = EffFn1 (ReduxEffect eff) (ReduxAction' action) (ReduxAction' action) 39 | 40 | -- | Allows `ReduxMiddleware` to wrap the `ReduxBaseDispatch` function to return a different result to be passed to the next `ReduxMiddleware`. 41 | type ReduxDispatch eff action result = EffFn1 (ReduxEffect eff) (ReduxAction' action) result 42 | 43 | -- | Simplified `Store` representation passed to each middleware. 44 | type ReduxMiddlewareAPI eff state action 45 | = { dispatch :: ReduxBaseDispatch eff action 46 | , getState :: Eff (ReduxEffect eff) state 47 | } 48 | 49 | -- | Function that composes dispatch functions. Purposely restricted to dispatching `action` types here. 50 | type ReduxMiddleware eff state action a b = ReduxMiddlewareAPI eff state action -> ReduxDispatch eff action a -> ReduxDispatch eff action b 51 | 52 | -- | Foreign Redux store creator function. 53 | foreign import data ReduxStoreCreator :: # Effect -> Type -> Type -> Type 54 | 55 | -- | Type alias for a foreign Redux store enhancer, taking a `ReduxStoreCreator` and returning a `ReduxStoreCreator`. 56 | type ReduxStoreEnhancer eff state action = ReduxStoreCreator eff state action -> ReduxStoreCreator eff state action 57 | 58 | -- | Type alias for a foreign `ReduxStore` 59 | type ReduxStore eff state action 60 | = { dispatch :: ReduxBaseDispatch eff action 61 | , getState :: Eff (ReduxEffect eff) state 62 | , subscribe :: Eff (ReduxEffect eff) Unit -> Eff (ReduxEffect eff) Unit 63 | , replaceReducer :: EffFn1 (ReduxEffect eff) (ReduxReducer state action) Unit 64 | } 65 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | --------------------------------------------------------------------------------