# @nichoth/state

> Abstract state container

Latest version **0.1.1** (published 2018-06-11) · ISC license · 27 weekly downloads

## Install

```sh
npm install @nichoth/state
pnpm add @nichoth/state
yarn add @nichoth/state
bun add @nichoth/state
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.1.1 |
| Published | 2018-06-11 |
| First published | 2015-10-08 |
| Weekly downloads | 27 |
| License | ISC |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 5 |
| Unpacked size | 13.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | nichoth |
| Maintainers | nichoth |

## Links

- npm: https://www.npmjs.com/package/@nichoth/state
- Repository: https://github.com/nichoth/state
- Homepage: https://github.com/nichoth/state#readme
- Issues: https://github.com/nichoth/state/issues
- npm.io page: https://npm.io/package/@nichoth/state

## Dependencies (5)

- [xtend](https://npm.io/package/xtend.md) ^4.0.1
- [lodash](https://npm.io/package/lodash.md) ^4.17.4
- [inherits](https://npm.io/package/inherits.md) ^2.0.3
- [deep-extend](https://npm.io/package/deep-extend.md) ^0.5.0
- [@nichoth/events](https://npm.io/package/@nichoth/events.md) ^0.6.5

## Recent versions

- 0.1.1 (latest) — 2018-06-11
- 0.1.0 — 2018-06-11
- 0.0.12 — 2018-04-25
- 0.0.11 — 2018-03-08
- 0.0.10 — 2018-01-25
- 0.0.9 — 2018-01-22
- 0.0.8 — 2018-01-22
- 0.0.7 — 2018-01-21
- 0.0.6 — 2018-01-18
- 0.0.5 — 2018-01-18
- 0.0.4 — 2017-11-07
- 0.0.3 — 2016-01-27
- 0.0.2 — 2015-10-14
- 0.0.1 — 2015-10-11
- 0.0.0 — 2015-10-08

## README

# old school mutable state

Abstract state container

This package provides minimal prototypes for creating state machines. The core is `index.js`, a class with 2 methods for subscribing to changes and publishing updates. All children inherit from this.

We use sorted lists of objects so frequently that `list.js` is included here, which has methods for basic crud operations.

There are several utility functions also -- `extend`, a helper for inheriting from this, `Merge`, which composes multiple state machines, and `map`.

## install 

    $ npm install @nichoth/state


## example

### inherit from this module

```js
var Store = require('../')
var xtend = require('xtend')
var assert = require('assert')

// you need to implement _state
// if _state is an object, it is deep cloned whenever we instantiate a
// new FooStore
var FooStore = Store.extend({
    _state: { foo: 'foo' },

    // **all methods should be synchronous**
    setFoo: function (value) {
        this._state.foo = value
        return this.publish()
    }
})

var fooStore = FooStore()

// get state
var state = fooStore.state()
console.log('initial state', state)
assert.deepEqual(state, { foo: 'foo' })

// subscribe to changes
var stopListening = fooStore.state(function onChange (state) {
    console.log('new state', state)
    assert.equal(state.foo, 'bar')
})
fooStore.setFoo('bar')

// unsubscribe
stopListening()
var stop = fooStore.state(state => assert.equal(state.foo, 'baz'))
fooStore.setFoo('baz')
stop()


// `_state` can be a function that returns initial state
var BarStore = Store.extend({
    _state: function (init) {
        return { bar: init }
    },

    setBar: function (val) {
        this._state.bar = val
        return this.publish()
    }
})

var barStore = BarStore('baz')
assert.equal(barStore.state().bar, 'baz')
```

### State.Merge

Compose multiple state machines, and get change events whenever one of
them changes

```js

// emit a change event whenever one of the children changes
var merged = Store.Merge({
    foo: fooStore,
    bar: barStore
})

var unlisten = merged.state(function onChange (state) {
    console.log('merged', state)
    assert.deepEqual(state, {
        foo: { foo: 'aaaaa' },
        bar: { bar: 'baz' }
    })
})

fooStore.setFoo('aaaaa')

unlisten()
```

### State.map

Take an existing store and return a new store that is mapped
by a predicate function

```js
var mapped = Store.map(function (state) {
    return xtend(state, {
        woo: 'woo'
    })
}, fooStore)

mapped.state(function onChange (state) {
    console.log('mapped', state)
    assert.deepEqual(state, { foo: 'hello', woo: 'woo' })
})

fooStore.setFoo('hello')
```

### struct
A simple observable object with one method, `.set`.

```js
var Struct = require('@nichoth/state/struct')
var assert = require('assert')

var myState = Struct({
    hello: 'world',
    foo: 'bar'
})

// do a shallow merge
myState.set({ hello: 'ok' })

assert.deepEqual(myState.state(), {
    hello: 'ok',
    foo: 'bar'
})
```

### List
A sorted list of objects

```js
var Store = require('../')
var ListStore = require('../list')
var assert = require('assert')

var Foos = Store.extend({
    // these are required
    idKey: 'id',
    sortBy: 'hello',
}, ListStore)

var foos = Foos()

console.log(foos.state())
assert.deepEqual(foos.state(), {
    data: {},
    sorted: [],
    hasFetched: false
})
```

#### list.get(array) => list

Set this store's list of sorted data
```js
// the get method assumes the list is *already* sorted
foos.get([{ id: 2, hello: 'ham' }, { id: 1, hello: 'world' }])
console.log(foos.state())
assert.deepEqual(foos.state(), {
    data: {
        '1': { id: 1, hello: 'world' },
        '2': { id: 2, hello: 'ham' }
    },
    sorted: [ { id: 2, hello: 'ham' }, { id: 1, hello: 'world' } ],
    hasFetched: true
})
```

#### list.add(object) => list

Add an element in the correct sorted position
```js
foos.add({ id: 3, hello: 'bar' })
assert.equal(foos.state().sorted[0].hello, 'bar')
```

#### list.edit(object) => list

Lookup an object by id, and update the given properties
```js
foos.edit({ id: 3, hello: 'baz' })
assert.equal(foos.state().sorted[0].hello, 'baz')
assert.equal(foos.state().data['3'].hello, 'baz')
```

#### list.delete(object) => list

Lookup an object by id and delete it from the store
```js
foos.delete({ id: 2 })
console.log(foos.state())
assert.deepEqual(foos.state(), {
    data: {
        '1': { id: 1, hello: 'world' },
        '3': { id: 3, hello: 'baz' }
    },
    sorted: [ { id: 3, hello: 'baz' }, { id: 1, hello: 'world' } ],
    hasFetched: true
})
```

---
_Source: https://npm.io/package/@nichoth/state · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
