JSPM

choo-pull

1.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1
  • Score
    100M100P100Q15251F
  • License MIT

Wrap handlers to use pull-stream

Package Exports

  • choo-pull

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 (choo-pull) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

choo-pull stability

npm version build status test coverage downloads js-standard-style

Wrap handlers to use pull-stream in a choo plugin. This is intended to go beyond basic choo usage, and tread into the domain of managing asynchronous complexity using streams / FRP.

While streams code takes longer to write up front, resulting code is generally stateless, pretty damn fast and surprisingly reusable. pull-streams are a minimal version of streams that weigh 200 bytes and handle backpressure phenomenally.

Usage

const pull = require('choo-pull')
const choo = require('choo')

const app = choo()
app.use(pull())

const tree = app.start()
document.body.appendChild(tree)

Now each handler in a model expects a valid through pull-stream to be returned synchronously. Initial data will be passed as the source, errors handling and done() calls are appended in the sink:

const through = require('pull-through')
const ws = require('pull-ws')
const xhr = require('xhr')

module.exports = {
  namespace: 'my-model',
  state: {
    count: 0
  },
  reducers: {
    increment: (data, state) => ({ count: state.count + data }),
    decrement: (data, state) => ({ count: state.count - data }),
  },
  subscriptions: {
    getDataFromSocket: (Send$) => {
      const ws$ = Ws$('wss://echo.websocket.org')
      return pull(ws$, Deserialize$(), Send$('performXhr'))
    }
  },
  effects: {
    performXhr: (state, Send$) => pull(Xhr$(), Deserialize$())
  }
}

function Xhr$ () {
  return through((data, cb) => {
    xhr('/foo/bar', { data: data }, (err, res) => {
      if (err) return cb(err)
      cb(null, res)
    })
  })
}

function Deserialize$ () {
  return through((data, cb) {
    try {
      cb(null, JSON.parse(data))
    } catch (e) {
      cb(e)
    }
  })
}

function Ws$ (url) {
  return ws(new window.WebSocket(url))
}

Using send()

Like all other API methods, so too does the send() method become a pull-stream. More specifically it becomes a through stream that takes the action name as the sole arugment, and pushes any results into any a connecting through or sink stream:

const through = require('pull-through')

module.exports = {
  state: {
    count: 0
  },
  reducers: {
    bar: (state) => ({ state.count + data })
  },
  effects: {
    callBar: (state, prev, Send$) => Send$('bar'),
    callFoo: (state, prev, Send$) => Send$('foo')
  }
}

// send('callFoo', 1)
// => state.count = 1

API

hooks = pull(opts)

Create an object of hooks that can be passed to app.use(). Internally ties into the following hooks:

  • wrapSubscriptions: changes the API of subscriptions to be (Send$)
  • wrapEffects: changes the API of effects to be (state, Send$)

The following options can be passed:

  • opts.subscriptions: default: true. Determine if subscriptions should be wrapped
  • opts.effects: default: true. Determine if effects should be wrapped

Incrementally enabling options can be useful when incrementally upgrading from a CSP-style codebase to a reactive / streaming one.

pull.subscription(subscription)

Wrap a single subscription. Useful to incrementally upgrade a CSP-style codebase to a reactive / streaming one.

pull.effect(effect)

Wrap a single effect. Useful to incrementally upgrade a CSP-style codebase to a reactive / streaming one.

FAQ

Why aren't reducers wrapped in pull-streams?

In choo@3 the internal workings demand that data always be returned synchronously. Because pull-stream returns data in a callback, reducers cannot be wrapped. Perhaps at some point we'll allow for a hybrid API, but at this point it's frankly not possible.

Installation

$ npm install choo-pull

License

MIT