Created
February 3, 2019 02:58
-
-
Save siassaj/03a6362ad66bfcd8d1b6ab5c5058e24f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { StateSoruce, Reducer } from '@cycle/state' | |
| import { Stream } from 'xstream' | |
| import { DOMSource, VNode } from '@cycle/dom' | |
| import { HTTPSource, Request } from '@cycle/http' | |
| type Payload = object | |
| interface StoreState = { | |
| userProfile: object | |
| } | |
| type ActionName = "reloadProfile" | "clearSession" | "whateverElse" | |
| interface Action { | |
| category: string | |
| name: ActionName | |
| payload: Payload | |
| } | |
| interface StoreSource { | |
| selectAction: (action: Action) => Stream<Payload> | |
| stream: Stream<StoreState> | |
| } | |
| interface UISources { | |
| DOM: DOMSource, | |
| state: StateSorurce | |
| store: StoreSource | |
| } | |
| interface UISinks { | |
| state: Stream<Reducer> | |
| store: Stream<Action> | |
| DOM: Stream<VNode> | |
| } | |
| interface StoreSources { | |
| HTTP: HTTPSource | |
| state: StateSource | |
| store: StoreSource | |
| } | |
| interface StoreSinks { | |
| HTTP: Stream<Request> | |
| state: Stream<Reducer> | |
| } | |
| // UI Component that displays user profile | |
| function UIMain(sources: UISources): UISinks { | |
| const clickReload$ = sources.DOM.select('.reload').events('click') | |
| const dispatchProfile$ = clickReload$.mapTo({ | |
| category: "reloadProfile", | |
| action: "reloadProfile", | |
| payload: {} | |
| }) | |
| const showActivityIndicator$ = clickReload$.mapTo(() => prev => ({ | |
| ...prev, | |
| showActivityIndicator = true | |
| })) | |
| const hideActivityIndicator$ = sources.store.select('reload').flatten().mapTo(() => prev => ({ | |
| ...prev, | |
| showActivityIndicator = false | |
| })) | |
| const view$ = xs.combine(sources.state.stream, sources.store.stream). | |
| map(state, store => ( | |
| div([ | |
| state.showActivityIndicator ? | |
| activityIndicator() | |
| : | |
| userProfile(store.userProfile) | |
| ]) | |
| )) | |
| return { | |
| DOM: view(sources.state.stream, sources.store.stream) | |
| state: xs.merge(showActivityIndicator$, hideActivityIndicator$) | |
| store: reloadProfile$ | |
| } | |
| } | |
| function StoreMain(sources: StoreSources): StoreSinks { | |
| const reloadProfile$ = sources.store.selectAction('reloadProfile') | |
| const requestProfile$ = reloadProfile$.mapTo({ | |
| category: 'requestProfile', | |
| url: "http://somePlace/api/v1/getProfile", | |
| }) | |
| const receiveProfile$ = sources.HTTP.select('requestProfile').flatten(). | |
| map(response => prev => ({ | |
| ...prev, | |
| userProfile: response.userProfile | |
| })) | |
| return { | |
| HTTP: requestProfile$ | |
| state: receiveProfile$ | |
| } | |
| } | |
| interface ActionLifecycleResponse { | |
| status: "received" | "getting" | "setting" | "failure" | |
| category: string | |
| payload: any | |
| } | |
| type ActionResponse$ = Stream<ActionLifecycleResponse> | |
| interface ActionComponentSources { | |
| action: Stream<Payload> | |
| HTTP: HTTPSource | |
| } | |
| interface ActionComponentSinks { | |
| action: Stream<ActionResponse$> | |
| HTTP: Stream<Request> | |
| } | |
| ActionComponent = (sources: ActionComponentSources) => ActionComponentSinks | |
| interface ActionDefinitions { | |
| [k: ActionName]: ActionComponent | |
| } | |
| function createStore(actionDefinitions: ActionDefinitions): store { | |
| const actionSources = constructActionSources | |
| const componentSinks = map(actionDefinitions, (component, actionName) => { | |
| innerSources = { | |
| ...actionSources, | |
| action: actionSources.action.select(actionName) | |
| } | |
| const sinks = component(innerSources) | |
| return { | |
| ...sinks, | |
| action: sinks.action.map(actionResponse$: ActionResponse$ => { | |
| actionResponse$.actionName = actionName | |
| return actionResponse$ | |
| }) | |
| } | |
| }) | |
| return mergeCompononentSinks(componentSinks) | |
| } | |
| storeSinks = createStore({ | |
| reloadProfile: (sources) => { | |
| //...do stuff | |
| return sinks | |
| }, | |
| clearSession: (sources) => { | |
| const clear$ = sources.action.mapTo(prev => { ...prev, userProfile: null }) | |
| return { | |
| state: clear$ | |
| } | |
| } | |
| }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment