Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

cycle-channel

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cycle-channel

A single pipeline of sources to sinks

  • 2.0.0
  • latest
  • Source
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

cycle-channel

Tests Stability Dependencies

Cycle.js is a fantastic framework for handling the cyclical stream-based nature of UI, but it doesn't give that full-framework feeling by itself. In comes cycle-channel, explained by the below image:

Explination

This means that cycle-channel is a single pipeline of driver sources to driver sinks. The core point of cycle-channel (and the sublibraries) is to provide a unified interface for data and actions and their intertwined behavior. This kind of logic often gets written by hand and instead I prefer to have something stable.

Usage

For this example I've removed the import statements for anything that isn't really important.

import {channel} from "cycle-channel"
import {stateDriver} from "cycle-channel"
import {dataDriver} from "cycle-channel"
import {viewEventSignals} from "cycle-channel-dom"
import {networkResponseSignals} from "cycle-channel-http"
import {storageReadSignals} from "cycle-channel-storage"
import intent from "snabbdom-intent"

// NOTE: See https://github.com/krainboltgreene/snabbdom-intents for more information
const intents = {
  onChangeSearch: intent({change: ["updateFormField", "fetchSearchResult"]})
}

// NOTE: This function will render our view layer.
const render = ({state}) => {

  // NOTE: See https://github.com/krainboltgreene/snabbdom-intents for more information
  const withSearch = intents.onChangeSearch({
    form: "search",
    field: "query",
  })

  return main({
    children: [
      h1({children: "Google"}),
      input(withSearch({children: state.ephemeral.forms.search.query})),
      p({children: "See below for the results"}),
      ul({children: mapValues((result) => li({children: result.title}))(state.resources.results)}),
    ],
  })
}
const application = ({view, network, storage}) => {
  return channel({
    // NOTE: Signals are streams of signal emits, mapped from sources. The below functions each know how to turn a native event from that source into a standardized signal that can be reacted to or transformed into a message.
    signals: [
      // NOTE: For example, this is a stream of signals from view layer events
      viewEventSignals(view),

      // NOTE: This is a stream of signals from http responses
      networkResponseSignals(network),

      // NOTE: This is a stream of signals from the local storage driver
      storageReadSignals(storage),
    ],

    // NOTE: This is the start of your application's state. You might want something more complicated than this.
    initialState: {},

    // NOTE: Reactions are the functions that fire in response to certain signals. They receive the current state and the payload). They return the next state:
    reactions: {
      // reaction:: State => {event?: Event, [name?: Key]: mixed} => State
      updateFormField: (state) => ({event, form, field}) => {
        return mergeDeepRight(
          state
        )(
          recordFrom(["ephemeral", "forms", form, field])(event.target.value)
        )
      },
      mergeResources: (state) => ({data}) => {
        return mergeDeepRight(
          state
        )({
          resources: treeify([groupBy(keyChain(["attributes", "type"])), indexBy(key("id"))])(data)
        })
      },
    },

    // NOTE: Transforms are functions that take state and a payload and turn them into transmissions meant for drivers. For example, you may want a button press to trigger a http request. They must return a Transmission:
    transformers: {
      // transform:: State => {event?: Event, [name: Key]?: mixed} => {driver: string, data: mixed}
      fetchSearchResult: (state) => ({event}) => {
        return {
          driver: "network",
          data: {
            method: "GET",
            url: `https://api.example.com/search?query=${event.target.value}`,
            headers: {Authorization: `Basic ${state.ephemeral.authorization}`},
          },
        }
      },
    },
    // NOTE: Drains are sinks that always happen, regardless of the type of message. Views are a good example, because state might have changed
    drains: {view: stateDriver(render)},

    // NOTE: Vents are sinks that only happen when a Message has the `driver` property of the same name as the key, so a the above search request would go down the network sink.
    vents: {
      network: dataDriver(),
      storage: dataDriver(),
    },
  })
}
const drivers = {
  view: makeDOMDriver("body"),
  network: makeHTTPDriver(),
  storage: storageDriver(),
}

run(application, drivers)

Keywords

FAQs

Package last updated on 26 Feb 2018

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc