npm install msgExports a single function which takes an object of name -> function pairs and contructs a data structure which can be used to make an Elm Architecture / Redux style app. Inspired by union-type.
295 bytes. No dependencies.
```
npm i -S msg
`js
import Message from 'msg'
const Route = ( model, path ) => { model.route = path; return model }
const Select = ( model, name ) => { model.selected = name; return model }
const Saved = ( model, name ) => { model.saved = true; return model }
const actions = { Route, Select, Saved }
const Action = Message( actions )
console.log( Action )
``
js`
console.log(Action.Route( '/' ))`
js`
Action.isPrototypeOf( Action.Route() ) //=> true
Action.isPrototypeOf( Action.Route ) //=> false
Message.prototype.isPrototypeOf( Action.Route() ) //=> true
Action.Route() instanceof Message //=> true
Define effects
`js`
const Effect = Message(
{ Save: ( message$, index ) => {
localStorage.setItem( 'selected', index )
return Action.Saved()
}})
Initialise model
`js`
const init = () =>
({ route: '/'
, selected: localStorage.getItem( 'selected' )
, names: [ 'Johnathan Best', 'Adonai Reynolds', 'Kasandra Ursler', 'Honora Bognár' ]
, saved: false
})
Define the view
Import update as render so it doesn't clash with our model update function
`js
import yo, { update as render } from 'yo-yo'
const view = message$ => model => yo
- message$( Action.Select( index ))}>
${ model.selected == index ? name.toUpperCase() : name }
)}
`Define flyd streams. Flyd has a good explanation in its README.
`js
const update = ( model, action ) => action.value( model, ...action.args )const instanceOf = type => msg =>
type.isPrototypeOf( msg )
import { stream, scan, map } from 'flyd'
import filter from 'flyd/module/filter'
const message$ = stream()
const action$ = filter( instanceOf( Action ), message$ )
const model$ = scan( update, init(), action$ ) // Contains the entire state of the application
const node$ = map( view( message$ ), model$ ) // Stream of DOM nodes to patch the document
`message$ is short for messageStream. message$ is a function which takes one or zero arguments. If you pass a value to action$, that becomes the value returned next time message$ is called with no argument.
`js
message$( 'example' )
message$() // => 'example'
`The
scan function is like reduce. It returns a new stream based on manipulating the stream passed as its third argument. The second argument is the initial value of the returned stream. Each time something is pushed onto action$ by calling action$( something ), scan runs update and passes it two arguments. 1: model - the last value passed to model$. 2: action - the last value passed to action$. The value returned by update becomes the new value of model$.
`js
const container = document.querySelector( '#app' )
scan( render, container, node$ )const effect$ = filter( instanceOf( Effect ), message$ )
map( effect => message$( effect.value( ...effect.args )), effect$ )
``