JSPM

  • Created
  • Published
  • Downloads 2533
  • Score
    100M100P100Q119678F
  • License MIT

Reactive library for state management, data fetching, caching

Package Exports

  • mutoid

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (mutoid) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Mutoid

Reactive library for state management, data fetching, caching (wip) with some utilities to use with React


Installation

To install the last version

yarn add mutoid rxjs fp-ts

if you want to use io-ts decoder in data fetching

yarn add io-ts

if you want also to use with react

yarn add react-dom react

Note rxjs, fp-ts, io-ts, react are a peer dependency for mutoid


State management

import * as MS from 'mutoid/lib/state'

Create store

in ctor we use memoization

const appStore = MS.ctor(() => ({ name: 'appStore' as const, initState: { userName: 'Marco' } }))
Read the status from anywhere
import { pipe } from 'fp-ts/lib/pipeable'
import * as T from 'fp-ts/lib/Task'
import * as C from 'fp-ts/lib/Console'

const program = pipe(
    MS.toTask(appStore),
    T.map(s => `Hello ${s.userName}`),
    T.chainIOK(C.log)
)

program()
Mutation -> mutationRunner
ctorMutation
declare const store: Lazy<Store<S>>
declare const id: number

declare const mutation: () => MS.ctorMutation(
    'mutation' as const,
    (id: number) => (currentState: S) => Observable<S>
)

const mutationR = MS.mutationRunner(store, mutation)
mutationR(id)

Mutation with deps

import { ajax, AjaxCreationMethod } from 'rxjs/ajax'

declare const store: Lazy<Store<S>>
declare const id: number
declare const deps: {
    ajax: AjaxCreationMethod
}

declare const mutation: (deps: typeof deps) => MS.ctorMutation(
    'mutation' as const,
    (id: number) => (currentState: S) => Observable<S>
)

const mutationR = MS.mutationRunner(store, mutation, {deps: {ajax: ajax}})
mutationR(id)
ctorPartialMutation

mutation runs only if the state matches the predicate, useful if your store is a state machine

declare const store: Lazy<Store<S>>
declare const id: number

declare const mutation: () => MS.ctorPartialMutation(
    'partialMutation' as const,
    (currentState: S): currentState is SS => currentState.type === 'ss',
    (id: number) => (currentState: SS) => Observable<S>
)

const mutationR = MS.mutationRunner(store, mutation)
mutationR(id)

if you want to kill the mutation MS.mutationRunner accept as third parameter "options" with propriety notifierTakeUntil?: Observable<unknown>

Store notifier

emit: initStore, mutationLoad, mutationStart, mutationEnd

declare const store: Lazy<Store<S>>

store().notifier$.subscribe(e =>
    Sentry.addBreadcrumb({
        category: 'mutation',
        message: action.type,
        level: Severity.Info,
        data: e,
    })
)

Data fetching

import * as MH from 'mutoid/lib/http'

ajaxToResource
import * as t from 'io-ts'
import { ajax } from 'rxjs/ajax'

export const somethingDecoders = {
    200: t.array(t.string).decode,
    400: t.string.decode,
}

export type somethingResource = MH.Resource<typeof somethingDecoders>

export const fetchSomething = () => MH.ajaxToResource(ajax('https://api.io'), somethingDecoders)
resourceFetcherToMutationEffect
import { map } from 'rxjs/operators'

export const fetchSomethingMutation = MS.ctorMutation(
    'fetchSomethingMutation' as const,
    MH.resourceFetcherToMutationEffect(fetchSomething, (o, s: state) => o.pipe(map(c => ({ ...s, something: c }))))
)

Rxjs

Operatos

import * as MRX from 'mutoid/lib/rsjx'

chainFirstIO

Perform a side effect and ignore the result

const o = of(1).pipe(MRX.chainFirstIO((uno: number) => IO.of(uno + 2))) // 1
chainIOK

Perform a side effect and keep the result

const o = of(1).pipe(MRX.chainIOK((uno: number) => IO.of(uno + 2))) // 3
runIO
const o = of(IO.of(1)).pipe(MRX.runIO())
extractE

Squash left and right

type e = E.either<L, R>
type result = L | R

Constructors

fromIO
const i = IO.of(1)

const o = MRX.fromIO(i).pipe(...)

React hooks

useSelector
const userName = useSelector(store, s => s.userName)
useMutation
const mutationR = useMutation(store, mutation)
useResourceFetcher
import { ajax } from 'rxjs/ajax'
import * as MH from 'mutoid/lib/http'

const somethingFetcher = () => MH.ajaxToResource(ajax('https://api.io'), decoders)

const [resource, dispatch] = useResourceFetcher(fetchSomething, iniState)

Run example

yarn dev-server

Test

Unit, lint and cs
yarn test
Type level
yarn test-type