@qvvg/sos

3.2.2 • Public • Published

State Owned State

Free the state, so your views can focus on the visual stuff.

People keep pretending they can make things hierarchical, categorizable and sequential when they can't. Everything is deeply intertwingled. –Theodor Holm Nelson

Install

npm install --save @qvvg/sos

Examples

Please see the examples directory for more.

// counter-domain.js
import {
  Domain,
  label,
  withName,
  deps,
  config,
  broadcast,
  handleInit,
  handleTell,
  handleContinue,
} from '@qvvg/sos'
import * as api from '../api/counter.js'

export default Domain([
  label('counter'),
  withName(),

  deps(() => ({
    getCount: api.getCount,
    saveCount: api.saveCount,
  })),

  config('delta', 1),

  broadcast('count', state => ({
    id: state.id,
    count: state.count,
  })),

  handleInit(async (ctx, id) => {
    const count = await ctx.deps.getCount(id)
    const subs = new Set()
    return ctx.Ok({id, count, subs})
  }),

  handleTell('subscribe', (ctx, state, sub) => {
    state.subs.add(sub)
    ctx.broadcast.count([sub], state)
    return ctx.Ok(state)
  }),

  handleTell('unsubscribe', (ctx, state, sub) => {
    state.subs.delete(sub)
    return ctx.Ok(state)
  }),

  handleTell('inc', (ctx, state, delta = ctx.config.delta) => {
    state.count += delta
    ctx.broadcast.count(state.subs, state)
    return ctx.Ok(state, ctx.Continue('save'))
  }),

  handleTell('dec', (ctx, state, delta = ctx.config.delta) => {
    state.count -= delta
    ctx.broadcast.count(state.subs, state)
    return ctx.Ok(state, ctx.Continue('save'))
  }),

  handleContinue('save', (ctx, state) => {
    ctx.deps.saveCount(state.id, state.count)
    return ctx.Ok(state)
  }),
])
// counter-sidecar.js
import {withSidecar, label, handleInit, handleTell, handleTerminate} from '@qvvg/sidecar'
import counter from './counter-domain.js'

export default withSidecar(
  label('counterSidecar'),

  deps(() => ({
    counter,
  })),

  handleInit((ctx, props) => {
    ctx.deps.counter.init(props.id)
    ctx.deps.counter.tell(props.id, 'subscribe', ctx.self())
    return ctx.Ok({id: props.id})
  }),

  handleTell(counter.events.count, (ctx, state, {count}) => {
    ctx.setProps({count})
    return ctx.Ok(state)
  }),

  handleTerminate((ctx, state, reason) => {
    ctx.deps.counter.tell(state.id, 'unsubscribe', ctx.self())
    return reason
  })
)
// counter-component
import React from 'react'
import withCounter from './counter-sidecar.js'
import counter from './counter-domain.js'

export const Counter = ({id, count, inc, dec}) =>
  count == null ? null : (
    <div>
      <h3>
        {id}: {count}
      </h3>
      <div>
        <button onClick={() => dec(id, 5)}>-5</button>
        <button onClick={() => dec(id)}>-1</button>
        <button onClick={() => inc(id)}>+1</button>
        <button onClick={() => inc(id, 5)}>+5</button>
      </div>
    </div>
  )

Counter.defaultProps = {
  count: null,
  inc: (id, ...args) => counter.tell(id, 'inc', ...args),
  dec: (id, ...args) => counter.tell(id, 'dec', ...args),
}

export default withCounter(Counter)
import React from 'react'
import Counter from './counter-component.js'

export default () => (
  <div>
    <Counter id="foo" />
    <Counter id="bar" />
    <Counter id="baz" />
  </div>
)

Readme

Keywords

none

Package Sidebar

Install

npm i @qvvg/sos

Weekly Downloads

17

Version

3.2.2

License

MIT

Unpacked Size

270 kB

Total Files

41

Last publish

Collaborators

  • qvvg