• Stars
    star
    207
  • Rank 183,858 (Top 4 %)
  • Language
    JavaScript
  • Created about 8 years ago
  • Updated about 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

๐Ÿ• composable unidirectional user interfaces using pull streams

Doge, the shiba inu
inu

๐Ÿ• composable unidirectional user interfaces using pull streams

table of contents
  • features
  • demos
  • example
  • concepts
  • api
  • install
  • inspiration
  • features

    • minimal size: inu + yo-yo + pull-stream weighs only ~8kb
    • app is a data structure: only need to learn 4 functions, automatically supports plugins
    • architecture is fractal: compose one app from many smaller apps
    • single source of truth: the state of your app is a single object tree
    • state is read-only: update state by dispatching an action, an object describing what happened
    • update with pure functions: updates are handled by a pure function, no magic
    • first-class side effects: initial state or updates can include an effect, an object describing what will happen
    • omakase: consistent flavoring with pull streams all the way down

    demos

    if you want to share anything using inu, add your thing here!

    example

    const { start, html, pull } = require('inu')
    const delay = require('pull-delay')
    
    const app = {
    
      init: () => ({
        model: 0,
        effect: 'SCHEDULE_TICK' // start perpetual motion
      }),
    
      update: (model, action) => {
        switch (action) {
          case 'TICK':
            return {
              model: (model + 1) % 60,
              effect: 'SCHEDULE_TICK'
            }
          default:
            return { model }
        }
      },
    
      view: (model, dispatch) => html`
        <div class='clock'>
          Seconds Elapsed: ${model}
        </div>
      `,
    
      run: (effect, sources) => {
        switch (effect) {
          case 'SCHEDULE_TICK':
            return pull(
              pull.values(['TICK']),
              delay(1000)
            )
        }
      }
    }
    
    const main = document.querySelector('.main')
    const { views } = start(app)
    
    pull(
      views(),
      pull.drain(function (view) {
        html.update(main, view)
      })
    )

    for a full example of composing multiple apps together, see source and demo.

    concepts

    imagine your appโ€™s current state is described as a plain object. for example, the initial state of a todo app might look like this:

    var initState = {
      model: {
        todos: [{
          text: 'Eat food',
          completed: true
        }, { 
          text: 'Exercise',
          completed: false
        }],
        visibilityFilter: 'SHOW_COMPLETED'
      },
      effect: 'FETCH_TODOS'
    }

    this state object describes the model (a list of todo items and an option for how to filter these items) and any optional effect (we immediately want to fetch for any new todo items).

    to change something in the state, we need to dispatch an action. an action is a plain JavaScript object (notice how we donโ€™t introduce any magic?) that describes what happened. here are a few example actions:

    { type: 'ADD_TODO', text: 'Go to swimming pool' }
    { type: 'TOGGLE_TODO', index: 1 }
    { type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }
    { type: 'LOAD_TODOS' }

    enforcing that every change is described as an action lets us have a clear understanding of whatโ€™s going on in the app. if something changed, we know why it changed. actions are like breadcrumbs of what has happened.

    finally, to tie state and actions together, we write an update function. again, nothing magic about it โ€” itโ€™s just a function that takes the model and action as arguments, and returns the next state of the app.

    it would be hard to write such a function for a big app, so we write smaller functions managing parts of the state:

    function visibilityFilter (model, action) {
      if (action.type === 'SET_VISIBILITY_FILTER') {
        return action.filter
      } else {
        return { model }
      }
    }
    
    function todos (model, action) {
      switch (action.type) {
        case 'ADD_TODO':
          return { model: model.concat([{ text: action.text, completed: false }]) }
        case 'TOGGLE_TODO':
          return {
            model: model.map((todo, index) =>
              action.index === index ?
                { text: todo.text, completed: !todo.completed } :
                todo
            )
          }
        case 'LOAD_TODOS':
          return { model, effect: 'FETCH_TODOS' }
        default:
          return { model }
      }
    }

    and we write another update function that manages the complete state of our app by calling those two update functions for the corresponding state keys:

    function appUpdate (model, action) {
      const todosState = todos(model.todos, action)
      const visibilityFilterState = visibilityFilter(model.visibilityFilter, action)
    
      return {
        model: {
          todos: todosState.model,
          visibilityFilter: visibilityFilter.model
        },
        effect: todosState.effect
      }
    }

    if any effect is returned by an update function, we want to run it. this run functions is able to listen to any future changes and return a stream of any new actions.

    here's how we handle our effect to fetch any todos, using pull-stream as pull:

    function appRun (effect, sources) {
      if (effect === 'FETCH_TODOS') {
        return pull(
          fetchTodos(),
          pull.map(todo => {
            return {
              type: 'ADD_TODO',
              text: todo.text
            }
          })
        )
      }
    }

    now that we have our state, changes, and side effects managed in a predictable (and easy-to-test) way, we want to view our epic todo list.

    here's a simplified view using yo-yo as html:

    function appView (model, dispatch) {
      return html`
        <div class='todos'>
          ${model.todos.map((todo, index) => html`
            <div class='todo'>
              ${todo.text}
              <button onclick=${toggleTodo(index)}
            </div>
          `)}
        </div>
      `
    
      function toggleTodo (index) {
        return (ev) => dispatch({ 'TOGGLE_TODO', })
      }
    }

    put it all together and we have an inu app!

    const app = {
      init: () => initState,
      update: appUpdate,
      view: appView,
      run: appRun
    }

    that's it for inu. note that we're only using plain functions and objects. inu (and inux) come with a few utilities to facilitate this pattern, but the main idea is that you describe how your state is updated over time in response to action objects, and 90% of the code you write is just plain JavaScript, with no use of inu itself, its APIs, or any magic.

    (credit @gaearon of redux for initial source of this intro)

    api

    where state is an object with a required key model and an optional key effect,

    an inu app is defined by an object with the following (optional) keys:

    • init: a function returning the initial state
    • update: a update(model, action) pure function, returns the new state
    • view: a view(model, dispatch) pure function, returns the user interface declaration
    • run: a run(effect, sources) function, returns an optional pull source stream of future actions

    inu = require('inu')

    the top-level inu module is a grab bag of all inu/* modules.

    you can also require each module separately like require('inu/start').

    sources = inu.start(app)

    sources is an object with the following keys:

    streams flow diagram

    * in this context, state-ful means that the pull source stream will always start with the last value (if any) first.

    inu.html === require('yo-yo') (for templating, virtual DOM "diffing")

    inu.pull === require('pull-stream') (for async event "piping")

    install

    npm install --save inu

    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.

    More Repositories

    1

    ssb-pub

    easily host your own Secure ScuttleButt (SSB) pub in a docker container
    Shell
    162
    star
    2

    mad-science-handbook

    โšก advanced programming with javascript
    82
    star
    3

    vas

    ๐ŸŒฑ composable client/server data services using pull streams
    JavaScript
    38
    star
    4

    push-stream

    โฉ minimal pipeable observables
    JavaScript
    33
    star
    5

    rimu

    Template language for structured data: functional YAML ๐ŸŒฑ
    Rust
    28
    star
    6

    transpilify

    ๐Ÿธ Applies browserify transforms to your source code, without actually bundling it.
    JavaScript
    27
    star
    7

    campjs-vii

    ๐Ÿ  CampJS talk: nature's best practices for distributed systems
    CSS
    21
    star
    8

    inux

    an experiment in opinionated helpers for `inu`
    JavaScript
    18
    star
    9

    polyledra-v1

    light-emitting polyhedron chandeliers ๐Ÿ’ก ๐ŸŒˆ ๐ŸŽ†
    JavaScript
    17
    star
    10

    mood-light

    mood light using electron and APA102C LEDs
    JavaScript
    16
    star
    11

    fs-template

    copy a template directory with variables injected
    JavaScript
    15
    star
    12

    evalify

    browserify transform to eval modules in node before exporting
    JavaScript
    14
    star
    13

    boot-to-electron

    13
    star
    14

    json-canon

    Serialize JSON into a canonical format.
    Rust
    13
    star
    15

    mintype

    ๐Ÿต minimal composable type abstraction
    JavaScript
    12
    star
    16

    ssb-bot

    conversational user interfaces for Scuttlebutt ๐Ÿค–
    JavaScript
    12
    star
    17

    hyper-fela

    hyperscript-style bindings for Fela
    JavaScript
    12
    star
    18

    uify

    ๐Ÿ˜Œ WIP the end of javascript fatigue: an opinionated set of tools for front-end apps
    JavaScript
    12
    star
    19

    metronome

    a simple metronome in rust โฐ ๐Ÿฅ
    Rust
    10
    star
    20

    read-audio

    ๐ŸŽค Read raw audio input as a stream of ndsamples
    JavaScript
    10
    star
    21

    callstep

    ๐Ÿšถ Promise-like async control flow library using plain functions
    JavaScript
    10
    star
    22

    solarmonk

    energy powered by the sun โ˜€๏ธ
    Arduino
    9
    star
    23

    slush-pages

    a slush generator for static pages using browserify
    JavaScript
    9
    star
    24

    blog.mikey.nz

    my blog as raw files, including drafts
    SCSS
    9
    star
    25

    hashicorp-deb

    helper scripts to build Debian packages (.deb files) for the Hashicorp ecosystem
    Shell
    9
    star
    26

    pull-test

    run assertion tests using pull streams
    JavaScript
    8
    star
    27

    incremental-id

    unique client ids using monotonic incremental numbers with no upper bound.
    JavaScript
    8
    star
    28

    butt-as-a-service

    [wip] provision and monitor Scuttlebutt bots in the cloud
    SaltStack
    8
    star
    29

    gyne

    declarative interface to manage a Docker swarm ๐Ÿ ๐Ÿœ
    JavaScript
    8
    star
    30

    typeof-is

    utility functions to check primitive types using typeof
    JavaScript
    8
    star
    31

    nest

    ๐Ÿฆ Use your filesystem as a nested data store!
    Rust
    7
    star
    32

    pull-xhr

    window.XMLHttpRequest as a (pseudo) pull-stream
    JavaScript
    7
    star
    33

    inu-plays-roguelike

    'Twitch Plays Pokรฉmon'-style 'Roguelike' game using `inu`
    JavaScript
    7
    star
    34

    webkit-window-manager

    7
    star
    35

    hyps

    a hyperscript-style module to create and update pure DOM elements.
    JavaScript
    7
    star
    36

    localcoins

    UNSUPPORTED command-line interface to LocalBitcoins API
    JavaScript
    6
    star
    37

    pixels-gl

    render pixels with webgl using regl
    JavaScript
    6
    star
    38

    infra

    Enspiral Root Systems infrastructure
    Ruby
    6
    star
    39

    ndsamples

    ๐Ÿ”ข ndsamples are ndarrays in a format for audio
    JavaScript
    6
    star
    40

    get-in

    get value of nested associative structure given array of keys
    JavaScript
    6
    star
    41

    cli-prompter

    interactive user prompts for the command-line interface
    JavaScript
    6
    star
    42

    node-audio-rms

    ใ€ฐ๏ธ stream real-time RMS from ndarrays of audio samples
    JavaScript
    5
    star
    43

    feathers-tcomb

    validate feathers services using tcomb
    JavaScript
    5
    star
    44

    uify-server

    browserify development and production server for real projects
    JavaScript
    5
    star
    45

    dweb-2018

    a tour of the Scuttlebutt ecosystem
    HTML
    5
    star
    46

    aspects

    before, after, and around hooks for sync and async functions
    JavaScript
    5
    star
    47

    zrpc-js

    rpc micro-services inspired by muxrpc and serverless functions, based on zmq
    JavaScript
    5
    star
    48

    ssb-archive

    build a static read-only web archive of ssb.
    Rust
    5
    star
    49

    inu-engine

    ๐Ÿถ ๐Ÿš€ composable user interface state and effects manager
    JavaScript
    5
    star
    50

    bigmath

    โž• โž– โŒ โž— arithmetic operators for arbitrary-precision numbers
    JavaScript
    5
    star
    51

    virtual-canvas

    canvas element for virtual-dom
    JavaScript
    5
    star
    52

    require-style

    require modules that target css in electron or the browser
    JavaScript
    5
    star
    53

    backplate

    ๐Ÿคš๐Ÿฝ๏ธ backtick (`) templates
    TypeScript
    5
    star
    54

    conjig

    ๐Ÿฃ a minimal universal configuration loader
    JavaScript
    4
    star
    55

    redux-state-reactor

    redux middleware to dispatch actions using state selectors
    JavaScript
    4
    star
    56

    beatbeam

    bitbeam but 10mm width instead of 8mm.
    OpenSCAD
    4
    star
    57

    pull-filereader

    read an HTML5 File object as a pull stream
    JavaScript
    4
    star
    58

    csg-to-mesh

    convert a csg.js solid to a simplicial complex mesh
    JavaScript
    4
    star
    59

    aburndance

    C++
    4
    star
    60

    feathers-action-types

    flux action types for feathers services
    JavaScript
    4
    star
    61

    localbitcoins

    UNSUPPORTED automates localbitcoins exchange
    Python
    4
    star
    62

    set-in

    set value of nested associative structure given array of keys
    JavaScript
    4
    star
    63

    feathers-action-reducer

    JavaScript
    4
    star
    64

    music-playground

    playground to learn music with synths and vocals ๐Ÿ’ƒ ๐ŸŽถ ๐ŸŽค
    JavaScript
    4
    star
    65

    pj

    pixel jockey: easy to use modular LED pixels that beat to music
    JavaScript
    4
    star
    66

    campjs-viii-ludditejs

    CampJS talk: how to JavaScript using only plain functions and objects.
    HTML
    4
    star
    67

    env-to-obj

    parse process.env to a deeply nested camelCase object
    JavaScript
    4
    star
    68

    pull-async

    create source pull-stream from async callback
    JavaScript
    3
    star
    69

    jseda

    electronic design automation (EDA) in JavaScript! ๐ŸŽ‰
    JavaScript
    3
    star
    70

    kaleidotube

    youtube kaleidoscopes ๐Ÿ“บ
    JavaScript
    3
    star
    71

    hardware-recorder

    3
    star
    72

    vf-types

    JavaScript
    3
    star
    73

    http-routes

    functional http router
    JavaScript
    3
    star
    74

    howtonetwork

    how to easily setup a network with a routerboard
    3
    star
    75

    cross-script

    cross-platform command script as subset of bash
    JavaScript
    3
    star
    76

    mandala

    playing around with mandalas
    JavaScript
    3
    star
    77

    tcomb-view

    JavaScript
    3
    star
    78

    http-compose

    minimal http handler composition
    JavaScript
    3
    star
    79

    ecstatic-lr

    `ecstatic` with `inject-lr-script` added
    JavaScript
    3
    star
    80

    vdom-render-stream

    stream objects to render virtual dom at element
    JavaScript
    3
    star
    81

    t-ndarray

    JavaScript
    3
    star
    82

    patchwork-downloader

    download latest Patchwork for your operating system!
    JavaScript
    3
    star
    83

    debian-package-builder

    build Debian packages (optionally using Docker for cross-compilation environment)
    Shell
    3
    star
    84

    cv.mikey.nz

    the course of my (professional) life
    CSS
    3
    star
    85

    ahdinosaur

    Personal GitHub profile
    3
    star
    86

    vibenet

    A silly Art~Hack project to play with Art-Net and Rust.
    Rust
    3
    star
    87

    bitbeam

    bitbeam library (ported from gridbeam library)
    OpenSCAD
    2
    star
    88

    bundle-cssify

    JavaScript
    2
    star
    89

    pull-opc

    pull streams for Open Pixel Control
    JavaScript
    2
    star
    90

    audio-poly-terrain

    JavaScript
    2
    star
    91

    btop

    ๐Ÿชฒ Get name of `Buffer` operation given `op`, `dtype`, and `endian`
    JavaScript
    2
    star
    92

    babel-preset-lts

    babel preset to use Node LTS (@4.2+) code in the browser
    JavaScript
    2
    star
    93

    audio-coder

    JavaScript
    2
    star
    94

    http-sender

    simple http final responder
    JavaScript
    2
    star
    95

    pull-compute

    compute across multiple threads using pull streams
    JavaScript
    2
    star
    96

    pull-secretstream

    libsodium secretstream as a pull stream
    JavaScript
    2
    star
    97

    kindling-browserify

    JavaScript
    2
    star
    98

    run-default

    run command, with default args if none given
    JavaScript
    2
    star
    99

    speaker-grill

    OpenSCAD
    2
    star
    100

    gatsby-starter

    JavaScript
    2
    star