\FF\D8\FF\E0\00JFIF\00\00\00d\00d\00\00\FF\FE\00\border bs:0 bc:#000000 ps:0 pc:#ffffff es:0 ec:#000000 ck:feee6c715d26fd9f38b0ca4278c05026\FF\DB\00C\00P7<F<2PFAFZUP_xxnnx\F5\AF\B9\91\C8\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\DB\00CUZZxix‚\EB\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\C0\00\00b\00d\00\FF\C4\00\00\00\00\00\00\00\00\00\00\00\00\00\00\FF\C4\00\00\00\00\00\00\00\00\00\00\001A!Q\FF\C4\00\00\00\00\00\00\00\00\00\00\00\00\00\FF\C4\00\00\00\00\00\00\00\00\00\00!1AQ\FF\DA\00\00\00?\00\F6\00\00\00\00\00\00\00\00\00\00\A0\00\00\C5\CF\F8\E7Ó\FCjD~\B9^\AD\%\B3]\D8cs-\BBs,-\A0\00"\80\00%\B83rÏ^K~F\A4ea\00E\00\C6\EE=u\B1\9B\D1\00@\00r\BE8\F9:\FE5#.M\00\E7\CB\C9q\CBq\D6\F2\BE\B7\C7>\C9n5×\D6?\BDê\9Ds\EBp\9F[`8m\B7)o\B5\E8\E6I\99\FE3]]A2\BA\8Cw\D6E\93\\DEv\C8\009\F2\F1NI?uc\\F5\EA\96k\xN<~buv\EA\C8\D7	\8B\84\CEcxI\BBg\AE\9E=\D6+n\EC\80\C8A\8C\AE\EB\CF\D5\DA\E9"2\A4\B9j5\EB\F3W\B63\96\B30Yu\DA\FC8\ED\DF\E7Ms\FB\F1\8E\B3\FA\EA\E8\E6(\883zs\F2_\8DFk\8Bh
\00\8C\DCw\D3R\B5+6X\BA\B2\C4j\AB0\B4\FCMw\C2I\8E\9B\E3\A9~9u\FA\D3l\80\C8%p\EE\FDn2€
\00$\FEj\C4e\A9\DB\~\95\A7\A5\80EK\BB\8DDsP\00@@AD'k\CF\E8\DB\D2(\80\9AK\D3\85\D6lb\F2\BA\8C*\80\00)\95
59\A3R:\F3\CE"\B6\80\88\00\00i1u4ê\E9\F2á\A6\A2\FACM\93WMb*\E0*\00\00\00\00\00(\A8\80\00\00\80\00\00\00\00\00\00\00\00\00\FF\D9<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>C///</title>
</head>
# figgy-pudding [![npm version](https://img.shields.io/npm/v/figgy-pudding.svg)](https://npm.im/figgy-pudding) [![license](https://img.shields.io/npm/l/figgy-pudding.svg)](https://npm.im/figgy-pudding) [![Travis](https://img.shields.io/travis/zkat/figgy-pudding.svg)](https://travis-ci.org/zkat/figgy-pudding) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/zkat/figgy-pudding?svg=true)](https://ci.appveyor.com/project/zkat/figgy-pudding) [![Coverage Status](https://coveralls.io/repos/github/zkat/figgy-pudding/badge.svg?branch=latest)](https://coveralls.io/github/zkat/figgy-pudding?branch=latest)

[`figgy-pudding`](https://github.com/zkat/figgy-pudding) is a small JavaScript
library for managing and composing cascading options objects -- hiding what
needs to be hidden from each layer, without having to do a lot of manual munging
and passing of options.

### The God Object is Dead!
### Now Bring Us Some Figgy Pudding!

## Install

`$ npm install figgy-pudding`

## Table of Contents

* [Example](#example)
* [Features](#features)
* [API](#api)
  * [`figgyPudding(spec)`](#figgy-pudding)
  * [`PuddingFactory(values)`](#pudding-factory)
    * [`opts.get()`](#opts-get)
    * [`opts.concat()`](#opts-concat)
    * [`opts.toJSON()`](#opts-to-json)
    * [`opts.forEach()`](#opts-for-each)
    * [`opts[Symbol.iterator]()`](#opts-symbol-iterator)
    * [`opts.entries()`](#opts-entries)
    * [`opts.keys()`](#opts-keys)
    * [`opts.value()`](#opts-values)

### Example

```javascript
// print-package.js
const fetch = require('./fetch.js')
const puddin = require('figgy-pudding')

const PrintOpts = puddin({
  json: { default: false }
})

async function printPkg (name, opts) {
  // Expected pattern is to call this in every interface function. If `opts` is
  // not passed in, it will automatically create an (empty) object for it.
  opts = PrintOpts(opts)
  const uri = `https://registry.npmjs.com/${name}`
  const res = await fetch(uri, opts.concat({
    // Add or override any passed-in configs and pass them down.
    log: customLogger
  }))
  // The following would throw an error, because it's not in PrintOpts:
  // console.log(opts.log)
  if (opts.json) {
    return res.json()
  } else {
    return res.text()
  }
}

console.log(await printPkg('figgy', {
  // Pass in *all* configs at the toplevel, as a regular object.
  json: true,
  cache: './tmp-cache'
}))
```

```javascript
// fetch.js
const puddin = require('figgy-pudding')

const FetchOpts = puddin({
  log: { default: require('npmlog') },
  cache: {}
})

module.exports = async function (..., opts) {
  opts = FetchOpts(opts)
}
```

### Features

* hide options from layer that didn't ask for it
* shared multi-layer options
* make sure `opts` argument is available
* transparent key access like normal keys, through a Proxy. No need for`.get()`!
* default values
* key aliases
* arbitrary key filter functions
* key/value iteration
* serialization
* 100% test coverage using `tap --100`

### API

#### <a name="figgy-pudding"></a> `> figgyPudding({ key: { default: val } | String }, [opts]) -> PuddingFactory`

Defines an Options constructor that can be used to collect only the needed
options.

An optional `default` property for specs can be used to specify default values
if nothing was passed in.

If the value for a spec is a string, it will be treated as an alias to that
other key.

##### Example

```javascript
const MyAppOpts = figgyPudding({
  lg: 'log',
  log: {
    default: () => require('npmlog')
  },
  cache: {}
})
```

#### <a name="pudding-factory"></a> `> PuddingFactory(...providers) -> FiggyPudding{}`

Instantiates an options object defined by `figgyPudding()`, which uses
`providers`, in order, to find requested properties.

Each provider can be either a plain object, a `Map`-like object (that is, one
with a `.get()` method) or another figgyPudding `Opts` object.

When nesting `Opts` objects, their properties will not become available to the
new object, but any further nested `Opts` that reference that property _will_ be
able to read from their grandparent, as long as they define that key. Default
values for nested `Opts` parents will be used, if found.

##### Example

```javascript
const ReqOpts = figgyPudding({
  follow: {}
})

const opts = ReqOpts({
  follow: true,
  log: require('npmlog')
})

opts.follow // => true
opts.log // => Error: ReqOpts does not define `log`

const MoreOpts = figgyPudding({
  log: {}
})
MoreOpts(opts).log // => npmlog object (passed in from original plain obj)
MoreOpts(opts).follow // => Error: MoreOpts does not define `follow`
```

#### <a name="opts-get"></a> `> opts.get(key) -> Value`

Gets a value from the options object.

##### Example

```js
const opts = MyOpts(config)
opts.get('foo') // value of `foo`
opts.foo // Proxy-based access through `.get()`
```

#### <a name="opts-concat"></a> `> opts.concat(...moreProviders) -> FiggyPudding{}`

Creates a new opts object of the same type as `opts` with additional providers.
Providers further to the right shadow providers to the left, with properties in
the original `opts` being shadows by the new providers.

##### Example

```js
const opts = MyOpts({x: 1})
opts.get('x') // 1
opts.concat({x: 2}).get('x') // 2
opts.get('x') // 1 (original opts object left intact)
```

#### <a name="opts-to-json"></a> `> opts.toJSON() -> Value`

Converts `opts` to a plain, JSON-stringifiable JavaScript value. Used internally
by JavaScript to get `JSON.stringify()` working.

Only keys that are readable by the current pudding type will be serialized.

##### Example

```js
const opts = MyOpts({x: 1})
opts.toJSON() // {x: 1}
JSON.stringify(opts) // '{"x":1}'
```

#### <a name="opts-for-each"></a> `> opts.forEach((value, key, opts) => {}, thisArg) -> undefined`

Iterates over the values of `opts`, 