# flipchain

> core chaining library, heavily based on [webpack-chain](https://github.com/mozilla-rpweb/webpack-chain)

Latest version **0.6.0** (published 2017-05-06) · MIT license · 0 weekly downloads

## Install

```sh
npm install flipchain
pnpm add flipchain
yarn add flipchain
bun add flipchain
```

## Health

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

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.6.0 |
| Published | 2017-05-06 |
| First published | 2017-03-15 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 4 |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 1 |
| Author | James |
| Maintainers | aretecode |
| Keywords | fluent, chain, fliphub-chain, webpack-chain, fusebox-chain, webpack, fliphub, flipbox, fusebox |

## Links

- npm: https://www.npmjs.com/package/flipchain
- Repository: https://github.com/fliphub/flipchain
- Homepage: https://github.com/fliphub/flipchain#readme
- Issues: https://github.com/fliphub/flipchain/issues
- npm.io page: https://npm.io/package/flipchain

## Dependencies (4)

- [deepmerge](https://npm.io/package/deepmerge.md) ^1.3.2
- [likeaboss](https://npm.io/package/likeaboss.md) *
- [arr-to-obj](https://npm.io/package/arr-to-obj.md) *
- [inspector-gadget](https://npm.io/package/inspector-gadget.md) *

## Alternatives

- [raw-loader](https://npm.io/package/raw-loader.md) — 4.3M weekly downloads
- [plop](https://npm.io/package/plop.md) — 1.4M weekly downloads
- [webpack-deadcode-plugin](https://npm.io/package/webpack-deadcode-plugin.md) — 80.3K weekly downloads
- [@storybook/preact-vite](https://npm.io/package/@storybook/preact-vite.md) — 54.2K weekly downloads
- [vite-plugin-transform](https://npm.io/package/vite-plugin-transform.md) — 2.4K weekly downloads

## Recent versions

- 0.6.0 (latest) — 2017-05-06
- 0.6.2 (web) — 2017-05-14
- 0.5.1 — 2017-04-30
- 0.5.0 — 2017-04-30
- 0.4.4 — 2017-04-19
- 0.4.2 — 2017-04-13
- 0.4.1 — 2017-04-11
- 0.4.0 — 2017-04-05
- 0.3.0 — 2017-04-04
- 0.2.0 — 2017-04-04
- 0.1.5 — 2017-03-29
- 0.1.4 — 2017-03-23
- 0.1.3 — 2017-03-20
- 0.1.2 — 2017-03-16
- 0.1.1 — 2017-03-15

## README

# ⛓ flipchain

[![NPM version][flipchain-npm-image]][flipchain-npm-url]
[![MIT License][license-image]][license-url]
[![fliphub][gitter-badge]][gitter-url]
[![flipfam][flipfam-image]][flipfam-url]

[flipchain-npm-image]: https://img.shields.io/npm/v/flipchain.svg
[flipchain-npm-url]: https://npmjs.org/package/flipchain
[license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat
[license-url]: https://spdx.org/licenses/MIT
[gitter-badge]: https://img.shields.io/gitter/room/fliphub/pink.svg
[gitter-url]: https://gitter.im/fliphub/Lobby
[flipfam-image]: https://img.shields.io/badge/%F0%9F%8F%97%20%F0%9F%92%A0-flipfam-9659F7.svg
[flipfam-url]: https://www.npmjs.com/package/flipfam


> core chaining library, heavily based on  [webpack-chain](https://github.com/mozilla-rpweb/webpack-chain), but not webpack-specific.


# 🏰 benefits

writing an api using flipchain means writing a single fluent api, but getting 3 apis as a result!
- 🍉 rehydratable configurations
- ⛓ fluent chainable api
- 🍦 object configs that are easily merged deep


# 🌊 what?
![fluent](https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Stone_skimming_-Patagonia-9Mar2010.jpg/1920px-Stone_skimming_-Patagonia-9Mar2010.jpg)

imagine there are 2 people by the water, & the goal is to make 10 splashes.

as with most skills, you get better at skipping rocks the more that you do it.
a lot of people cannot skip rocks, or they do not like to skip rocks, but they can still throw rocks and make a splash. think of this like non-fluent/vanilla-calls
```js
Chain.prop()
Chain.longer()
Chain.intoSomeShapes()
```

or throwing a really huge rock into the water, and getting the splashes to make more splashes.
```js
Chain.from({
  prop: null,
  longer: null,
  intoSomeShapes: null,
})
```


![pebbles](http://www.joulesevans.com/wp-content/uploads/2012/01/pebbles-mentor-page.jpg)
using method chaining looks similar to skipping rocks
```js
Chain
  .prop()
  .longer()
  .intoSomeShapes()
```

writing an application with a fluent interface allows people to use it all three ways, and you only have to write it one way.


# 📘 examples

## 👋 intro

```js
const ChainedMap = require('./ChainedMapExtendable')

class EasyFluent extends ChainedMap {
  constructor(parent) {
    super(parent)

    // extend a list of strings for easy chainable methods
    this.extend(['eh'])

    // same as .extend,
    // but when called with no arguments,
    // default is used (`true` in this case)
    // third param is optionally a prefix for inversified
    // for example, `no` => `noCanada()` for inverse value
    this.extendPrefixed(['canada'], true, 'no')
  }

  // if more advanced data changes are needed
  // or if the syntax is preferred for use with typescript or flowtype
  // .set, .get, .has are available
  igloo(igloo) {
    this.set('igloo', igloo)
    return this
  }

  toConfig() {
    return this.entries()
  }
}

// {igloo: 'fire', canada: false, eh: 'moose'}
const config = new EasyFluent()
  .igloo('fire')
  .noCanada()
  .eh('moose')
  .toConfig()

// this is == config
const hydrated = new EasyFluent()
  .from(config)
  .toConfig()

// canada is now true
const merged = new EasyFluent()
  .merge(config)
  .merge({canada: true})
  .toConfig()
```


## 🕳🏊 advanced

```js
const ChainedMap = require('./ChainedMapExtendable')
const ChainedSet = require('./ChainedSet')

class Advanced extends ChainedMap {
  static init(parent) {
    return new Advanced(parent)
  }
  constructor(parent) {
    super(parent)
    this.list = new ChainedSet(this)
    this.extend(['eh'])
    this.extendWith(['canada'], true)
  }

  addName(name) {
    this.list.add(name)
    return this
  }

  igloo(igloo) {
    this.set('igloo', igloo)
    return this
  }

  toConfig() {
    return Object.assign(this.entries(), {
      list: this.list.values().map(name => name),
    })
  }

  // since we have additional data that is not simple key value
  // we do additional (albeit easy) steps to rehydrate
  from(obj) {
    super.from(obj)

    Object
      .keys(obj)
      .forEach(key => {
        const val = obj[key]
        switch (key) {
          case 'list': return val
            .filter(name => name)
            .forEach(name => this.addName(name))
        }
      })

    return this
  }

  // same with `from`
  // we do additional simple steps to merge in lists
  merge(obj) {
    Object
      .keys(obj)
      .filter(key => obj[key])
      .forEach(key => {
        const val = obj[key]
        switch (key) {
          case 'list': return val
            .filter(name => name)
            .forEach(v => this.addName(v))
        }
      })

    // built-in merging
    // can use `.mergeReal` to merge only `real` values
    // and `.merge` to merge any
    super.merge(obj)

    return this
  }
}

const chain = Advanced
  .init()
  .igloo('brr')
  .canada()
  .eh('eh!')
  .addName('thing one')
  .addName('thing two')

// true, `eh!`
chain.has('igloo')
chain.get('eh')

const result = chain.toConfig()

const hydrated = Advanced
  .init()
  .from(result)
  .toConfig()

const merged = Advanced
  .init()
  .merge(hydrated)
  .merge({igloo: 'whaaaat'})

// can use toConfig,
// and safely continue editing `merged`
// with a snapshot of the object data saved as `mergedResult`
const mergedResult = merged.toConfig()

// hydrated === result === {
//   igloo: 'brr',
//   canada: 'canada',
//   eh: 'eh!',
//   list: [ 'thing one', 'thing two' ]
// }

// merged === {
//   igloo: 'whaaaat',
//   canada: 'canada',
//   eh: 'eh!',
//   list: [ 'thing one', 'thing two' ]
// }
```

# 🌊 types
- there are [jsdoc blocks](http://usejsdoc.org/index.html) for all methods

# 🌐 api
- every chain has `.className` for easy debugging
- every chain has this.parent
- and this.parent is hidden on inspection by [🕵🗜 inspector-gadget](https://www.npmjs.com/package/inspector-gadget) for easier debugging

### ChainedSet
- [Set](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Set)
- prepend => this
- clear => this
- delete => this
- values => array of entries
- has => boolean
- merge => merge an object into the chain
- when => conditional instance callback

### ChainedMap
- [Map](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map)

#### extendAlias
- `(methodsToAlias: Array<string>, methodToAlias: string, [thisArg])`
- alias a list of methods
- @returns `this`

### from
- `(obj: Object)`
- checks each property of the object
- calls the chains accordingly
- rehydrates a chain from an object


### other
- decorateParent (using [childparent](https://www.npmjs.com/package/childparent))
- clear() => this // clearsAll
- delete(key) => this
- entries => {keysAndValues}
- values => Object.values
- get(key) => entry
- has(key) => boolean
- set(key, val) => this

##### if key is an array, merge in the value,
##### usually should use ChainedSet for this
- concat(key, val) => this
- append(key, val) => this

##### merging
- mergeReal(obj) => this // only merges non-undefined values
- merge(obj) => this
- clean => this
- when => conditional instance callback




# 🔗 links & more
- [Martin Fowler on FluentInterface](https://www.martinfowler.com/bliki/FluentInterface.html)

#  `chainMapTill`
lets you chain until the required keys are set via chains, or if they are passed in, then it auto returns `parent`

# `chainedMapExtendable`
- has chains with `.extends` able to use `default` values when calling it
- also can add `prefixes` (default `no`) so if you use `cache` default `true`, it can add `noCache` which does the inverse
- set up for being chains of chains when you add a few decorating chains dynamically


# 📝🌊 TODO

```js
  // using `izz` to validate types when setting
  this.extendType(['str'], 'string')
```

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