Skip to content

Instantly share code, notes, and snippets.

@hannahhoward
Last active June 14, 2019 23:56
Show Gist options
  • Select an option

  • Save hannahhoward/cdfec536be939c515dd6809f718b2de1 to your computer and use it in GitHub Desktop.

Select an option

Save hannahhoward/cdfec536be939c515dd6809f718b2de1 to your computer and use it in GitHub Desktop.
import { SignalGraphBuilder, addPrimary, addDependency, addDerived } from '@rxreact/signal'
import { withLatestFrom, flatMap, map, filter } from 'rxjs/operators'
import { merge, pipe, Observable, combineLatest } from 'rxjs'
import { LoginResponse, LoginSuccess, LoginFailure, API, AuthStatus } from "./types"
import { api } from "./api"
const makeAuthStatus = map<LoginSuccess, AuthStatus>(({ data: { userToken } }: LoginSuccess) => ({
status: 'authorized',
token: userToken
}))
const makeLoginAttempts = (
submitButton$: Observable<void>,
username$: Observable<string>,
password$: Observable<string>
) => submitButton$.pipe(withLatestFrom(username$, password$))
const makeLoginResponses = (loginAttempts$: Observable<[void, string, string]>, api: API) =>
loginAttempts$.pipe(flatMap(([_, username, password]) => api.login({ username, password })))
const makeLoginInProgress = (
loginAttempts$: Observable<[void, string, string]>,
loginResponses$: Observable<LoginResponse>
) => merge(loginAttempts$.pipe(map(_ => true)), loginResponses$.pipe(map(_ => false)))
const makeLoginSuccesses = filter(
(loginResponse: LoginResponse): loginResponse is LoginSuccess =>
loginResponse.status === 'success'
)
const makeLoginFailures = filter(
(loginResponse: LoginResponse): loginResponse is LoginFailure =>
loginResponse.status === 'failure'
)
const makeLoginFailureMessage = (
loginAttempts$: Observable<[void, string, string]>,
loginFailures$: Observable<LoginFailure>
) =>
merge(
loginAttempts$.pipe(map(_ => '')),
loginFailures$.pipe(map(({ error: { message } }) => message))
)
type SignalsType = {
username$: string
password$: string
submitButton$: void
loginAttempts$: [void, string, string]
loginResponses$: LoginResponse
loginInProgress$: boolean
loginSuccesses$: LoginSuccess
loginFailures$: LoginFailure
loginFailureMessage$: string
authStatus$: AuthStatus
}
type Dependencies = {
api: API
}
const signalGraph = new SignalGraphBuilder<SignalsType, Dependencies>()
.define(addPrimary('username$'))
.define(
addPrimary('password$'),
addPrimary('submitButton$'),
addDependency('api', api),
addDerived('loginAttempts$', makeLoginAttempts, 'submitButton$', 'username$', 'password$'),
addDerived('loginResponses$', makeLoginResponses, 'loginAttempts$', 'api'),
addDerived('loginInProgress$', makeLoginInProgress, 'loginAttempts$', 'loginResponses$'),
addDerived('loginSuccesses$', makeLoginSuccesses, 'loginResponses$'),
addDerived('loginFailures$', makeLoginFailures, 'loginResponses$'),
addDerived(
'loginFailureMessage$',
makeLoginFailureMessage,
'loginAttempts$',
'loginFailures$'
),
addDerived('authStatus$', makeAuthStatus, 'loginSuccesses$')
)
.initializeWith({
loginInProgress$: false,
loginFailureMessage$: '',
username$: '',
password$: '',
authStatus$: { status: 'unauthorized' }
})
.build()
import { Dependency } from '@rxreact/signal'
import { api } from "./api"
export default Dependency(api)
import { DerivedSignal } from '@rxreact/signal'
import { map } from "rxjs/operators"
import { LoginSuccess, AuthStatus } from "../types"
import loginSuccesses$ from "./loginSuccesses"
export const makeAuthStatus = map<LoginSuccess, AuthStatus>(({ data: { userToken } }: LoginSuccess) => ({
status: 'authorized',
token: userToken
}))
export default DerivedSignal(loginSuccesses$, makeAuthStatus, { status: 'unauthorized' })
import { DerivedSignal, gate } from '@rxreact/signal'
import { Observable } from 'rxjs'
import username$ from "../inputs/username"
import password$ from "../inputs/password"
import submitButton$ from "../triggers/submitButton"
export const makeLoginAttempts = (
submitButton$: Observable<void>,
username$: Observable<string>,
password$: Observable<string>
) => submitButton$.pipe(
gate(username$, password$))
export default DerivedSignal(username$, password$, submitbutton$, makeLoginAttempts)
import { DerivedSignal } from '@rxreact/signal'
import { map } from "rxjs/operators"
import { merge, Observable } from "rxjs"
import { LoginFailure } from "../types"
import loginAttempts$ from "./loginSuccesses"
import loginFailures$ from "./loginFailures"
const makeLoginFailureMessage = (
loginAttempts$: Observable<[string, string]>,
loginFailures$: Observable<LoginFailure>
) =>
merge(
loginAttempts$.pipe(map(_ => '')),
loginFailures$.pipe(map(({ error: { message } }) => message))
)
export default DerivedSignal(loginAttempts$, loginFailures$, makeLoginFailureMessage, '')
import { DerivedSignal } from '@rxreact/signal'
import { filter } from "rxjs/operators"
import { LoginResponse, LoginFailure } from "../types"
import loginResponses$ from "./loginResponses"
export const makeLoginFailures = filter(
(loginResponse: LoginResponse): loginResponse is LoginFailure =>
loginResponse.status === 'failure'
)
export default DerivedSignal(loginResponses$, makeLoginFailure)
import { DerivedSignal } from '@rxreact/signal'
import { map } from "rxjs/operators"
import { merge, Observable } from "rxjs"
import { LoginResponse } from "../types
import loginAttempts$ from "./loginAttempts"
import loginResponses$ from "./loginResponses"
export const makeLoginInProgress = (
loginAttempts$: Observable<[string, string]>,
loginResponses$: Observable<LoginResponse>,
) => merge(loginAttempts$.pipe(map(_ => true)), loginResponses$.pipe(map(_ => false)))
export default DerivedSignal(loginAttempts$, loginResponses$, makeLoginInProgress, false)
import { DerivedSignal } from '@rxreact/signal'
import { flatMap } from "rxjs/operators"
import { Observable } from "rxjs"
import { API } from "types"
import api from "../dependencies/api"
import loginAttempts$ from "./loginAttempts"
export const makeLoginResponses = (loginAttempts$: Observable<[string, string]>, api: API) =>
loginAttempts$.pipe(
flatMap(([username, password]) => api.login({ username, password }))
)
const LoginResponseSignal = DerivedSignal(loginAttempts$, api, makeLoginResponses)
import { DerivedSignal } from '@rxreact/signal'
import { filter } from "rxjs/operators"
import loginResponses$ from "./loginResponses"
export const makeLoginSuccesses = filter(
(loginResponse: LoginResponse): loginResponse is LoginSuccess =>
loginResponse.status === 'success'
)
export default DerivedSignal(loginResponses$, makeLoginSuccess)
import { InputSignal } from '@rxreact/signal'
export default InputSignal('')
import { TriggerSignal } from "@rxreact/signal"
export default TriggerSignal()
import { InputSignal } from '@rxreact/signal'
export default InputSignal('')
import { SignalGraph } from '@rxreact/signal'
import api from "./dependencies/api"
import username$ from "./inputs/username"
import password$ from "./inputs/password"
import submitButton$ from "./triggers/submitButton"
import loginAttempts$ from "./derivedSignals/loginAttempts"
import loginResponses$ from "./derivedSignals/loginResponses"
import loginInProgress$ from "./derivedSignals/loginInProgress"
import loginSuccesses$ from "./derivedSignals/loginSuccesses"
import loginFailures$ from "./derivedSignals/loginFailures"
import authStatus$ from "./derivedSignals/authStatus"
import loginFailureMessage$ from "./derivedSignals/loginFailureMessage"
export default SignalGraph({
username$,
password$,
submitButton$,
loginAttempts$,
loginResponses$,
loginInProgress$,
loginSuccesses$,
loginFailures$,
loginFailureMessage$,
authStatus$,
api
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment