Home

Awesome

inux

an experiment in opinionated helpers for inu

npm install --save inux

robot doge

demos

philosophy

inu provides the foundation, inux lets us fly. :)

concepts

inux introduces some opinionated concepts to inu:

action or effect type

a unique String or Symbol that corresponds to a type of action or effect payload

const SET_TEXT = 'NOTEPAD_SET_TEXT'
// or
const SET_TEXT = Symbol('setText')

action or effect creator

a function that returns an action or effect object of the form { type, payload }

function setText (text) {
  return {
    type: SET_TEXT,
    payload: text
  }
}

domain

like an inu app, but

in this example, textEditor refers to a hypothetical re-usable view component.

{
  name: 'notepad',
  init: {
    model: '',
    effect: 
  }
  update: {
    [SET_TEXT]: (model, text) {
      return text
    }
  },
  routes: [
    ['/notepad', function (params, model, dispatch) {
      return html`
        <div>
          ${textEditor(model.notepad, save)}
        </div>
      `

      function save (text) {
        dispatch(setText(text))
      }
    }]
  ]
}

enhancer

a function that take an inu app and return another inu app

function log (app) {
  return extend(app, {
    init: () => {
      const state = app.init()
      console.log('init:', state)
      return state
    },
    update: (model, action) => {
      console.log('update before:', model, action)
      const state = app.update(model, action)
      console.log('update after:', state)
      return state
    },
    run: (effect, sources) => {
      console.log('run', effect)
      return app.run(effect, sources)
    }
  })
}

(for a better inu log enhancer, see inu-log)

app

a list of domains to become a single inu app

each domain is a group of functionality corresponding to a small specific theme in your overall app.

[
  notepad,
  settings,
  auth
]

example

const { start, html } = require('inu')
const { App, Domain, Action } = require('inux')
const extend = require('xtend')

const INCREMENT = Symbol('increment')
const DECREMENT = Symbol('decrement')
const SET = Symbol('set')

const increment = Action(INCREMENT)
const decrement = Action(DECREMENT)
const set = Action(SET)

const view = (model, dispatch) => html`
  <div>
    <button onclick=${(e) =>
      dispatch(decrement())
    }> - </button>
    <input type='number'
      oninput=${(ev) => {
        dispatch(set(Number(ev.target.value)))
      }}
      value=${model}
    />
    <button onclick=${(e) =>
      dispatch(increment())
    }> + </button>
  </div>
`

const counter = Domain({
  name: 'counter',
  init: () => ({ model: 0 }),
  update: {
    [INCREMENT]: (model) => ({ model: model + 1 }),
    [DECREMENT]: (model) => ({ model: model - 1 }),
    [SET]: (model, value) => ({ model: value })
  },
  routes: [
    ['/', (params, model, dispatch) => {
      return view(model.counter, dispatch)
    }]
  ]
})

const app = App([
  counter
])

// const sources = start(app) ...

usage

inux = require('inux')

inux.Domain(Object domain)

extends domain.update and domain.run with handleActions and handleEffects, respectively.

inux.App(Array domains)

combines an Array of inux domains into a single inu app.

each domains's model is namespaced to domain.name, any domains's effect is added to an Array of effects.

also

inux.Action(String|Symbol type, Function payloadCreator)

inux.Effect(String|Symbol type, Function payloadCreator)

inux.Event(String|Symbol type, Function payloadCreator)

create an action or effect creator.

creator returns object of form

{
  type: type,
  payload: payloadCreator(...args)
}

inux.run(effect)

creates action objects to run an effect.

corresponding inux.apps.run update:

{
  [RUN]: (model, effect) => ({ model, effect })
}

inux.apps.run

app to handle run actions.

inux.apps.href

app to track window.location.href.

inux.combine(Array apps)

combines an array of apps into a single app.

inux.route(Object app, Function viewCreator)

given an app with app.routes

and a function of the form (routes) => (model, dispatch) => ...,

creates the router with Router(app.routes) and sets the corresponding view as app.view.

inux.Router(Array routes)

given an array of routes, return a router using sheet-router.

the last route will be used as the default route.

inux.handleActions(Object actionHandlers)

given an Object of String or Symbol keys to action handlers, returns a single update Function.

each String or Symbol key corresponds to an action.type.

each action handler is a Function of the form (model, action.payload) => state.

inux.handleEffects(Object effectHandlers)

given an Object of String or Symbol keys to effect handlers, returns a single update Function.

each String or Symbol key corresponds to an effect.type.

each effect handler is a Function of the form (effect.payload, sources) => nextActions or null.

inux.scopeUpdate(Function update, String key)

given an update function and a key, returns a new update function that namespaces updates at the key.

inux.reduceUpdates(Array updates)

given a list of update functions, return a new update function that is the result of applying all of them.

inux.runMany(Array runs)

given a list of run functions, return a new run function that is the result of applying all of them.

inspiration

license

The Apache License

Copyright © 2016 Michael Williams

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.