7.5 KiB
Note: pending imminent deprecation
This module will be deprecated once npm v7 is released. Please do not rely on it more than absolutely necessary (ie, only if you are depending on it for use with npm v6 internal dependencies).
figgy-pudding
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
// 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.
= PrintOpts(opts)
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'
}))
// fetch.js
const puddin = require('figgy-pudding')
const FetchOpts = puddin({
log: { default: require('npmlog') },
cache: {}
})
.exports = async function (..., opts) {
module= FetchOpts(opts)
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
> 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
const MyAppOpts = figgyPudding({
lg: 'log',
log: {
default: () => require('npmlog')
,
}cache: {}
})
> 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
const ReqOpts = figgyPudding({
follow: {}
})
const opts = ReqOpts({
follow: true,
log: require('npmlog')
})
.follow // => true
opts.log // => Error: ReqOpts does not define `log`
opts
const MoreOpts = figgyPudding({
log: {}
})MoreOpts(opts).log // => npmlog object (passed in from original plain obj)
MoreOpts(opts).follow // => Error: MoreOpts does not define `follow`
> opts.get(key) -> Value
Gets a value from the options object.
Example
const opts = MyOpts(config)
.get('foo') // value of `foo`
opts.foo // Proxy-based access through `.get()` opts
> 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
const opts = MyOpts({x: 1})
.get('x') // 1
opts.concat({x: 2}).get('x') // 2
opts.get('x') // 1 (original opts object left intact) opts
> 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
const opts = MyOpts({x: 1})
.toJSON() // {x: 1}
optsJSON.stringify(opts) // '{"x":1}'
> opts.forEach((value, key, opts) => {}, thisArg) -> undefined
Iterates over the values of opts
, limited to the keys
readable by the current pudding type. thisArg
will be used
to set the this
argument when calling the
fn
.
Example
const opts = MyOpts({x: 1, y: 2})
.forEach((value, key) => console.log(key, '=', value)) opts
> opts.entries() -> Iterator<[[key, value], ...]>
Returns an iterator that iterates over the keys and values in
opts
, limited to the keys readable by the current pudding
type. Each iteration returns an array of [key, value]
.
Example
const opts = MyOpts({x: 1, y: 2})
...opts({x: 1, y: 2}).entries()] // [['x', 1], ['y', 2]] [
> opts[Symbol.iterator]() -> Iterator<[[key, value], ...]>
Returns an iterator that iterates over the keys and values in
opts
, limited to the keys readable by the current pudding
type. Each iteration returns an array of [key, value]
.
Makes puddings work natively with JS iteration mechanisms.
Example
const opts = MyOpts({x: 1, y: 2})
...opts({x: 1, y: 2})] // [['x', 1], ['y', 2]]
[for (let [key, value] of opts({x: 1, y: 2})) {
console.log(key, '=', value)
}
> opts.keys() -> Iterator<[key, ...]>
Returns an iterator that iterates over the keys in opts
,
limited to the keys readable by the current pudding type.
Example
const opts = MyOpts({x: 1, y: 2})
...opts({x: 1, y: 2}).keys()] // ['x', 'y'] [
> opts.values() -> Iterator<[value, ...]>
Returns an iterator that iterates over the values in
opts
, limited to the keys readable by the current pudding
type.
Example
’
const opts = MyOpts({x: 1, y: 2})
...opts({x: 1, y: 2}).values()] // [1, 2] [