1 |
3a515b92
|
cagy
|
# Note: pending imminent deprecation
|
2 |
|
|
|
3 |
|
|
**This module will be deprecated once npm v7 is released. Please do not rely
|
4 |
|
|
on it more than absolutely necessary (ie, only if you are depending on
|
5 |
|
|
it for use with npm v6 internal dependencies).**
|
6 |
|
|
|
7 |
|
|
----
|
8 |
|
|
|
9 |
|
|
# 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/npm/figgy-pudding.svg)](https://travis-ci.org/npm/figgy-pudding) [![Coverage Status](https://coveralls.io/repos/github/npm/figgy-pudding/badge.svg?branch=latest)](https://coveralls.io/github/npm/figgy-pudding?branch=latest)
|
10 |
|
|
|
11 |
|
|
[`figgy-pudding`](https://github.com/npm/figgy-pudding) is a small JavaScript
|
12 |
|
|
library for managing and composing cascading options objects -- hiding what
|
13 |
|
|
needs to be hidden from each layer, without having to do a lot of manual munging
|
14 |
|
|
and passing of options.
|
15 |
|
|
|
16 |
|
|
### The God Object is Dead!
|
17 |
|
|
### Now Bring Us Some Figgy Pudding!
|
18 |
|
|
|
19 |
|
|
## Install
|
20 |
|
|
|
21 |
|
|
`$ npm install figgy-pudding`
|
22 |
|
|
|
23 |
|
|
## Table of Contents
|
24 |
|
|
|
25 |
|
|
* [Example](#example)
|
26 |
|
|
* [Features](#features)
|
27 |
|
|
* [API](#api)
|
28 |
|
|
* [`figgyPudding(spec)`](#figgy-pudding)
|
29 |
|
|
* [`PuddingFactory(values)`](#pudding-factory)
|
30 |
|
|
* [`opts.get()`](#opts-get)
|
31 |
|
|
* [`opts.concat()`](#opts-concat)
|
32 |
|
|
* [`opts.toJSON()`](#opts-to-json)
|
33 |
|
|
* [`opts.forEach()`](#opts-for-each)
|
34 |
|
|
* [`opts[Symbol.iterator]()`](#opts-symbol-iterator)
|
35 |
|
|
* [`opts.entries()`](#opts-entries)
|
36 |
|
|
* [`opts.keys()`](#opts-keys)
|
37 |
|
|
* [`opts.value()`](#opts-values)
|
38 |
|
|
|
39 |
|
|
### Example
|
40 |
|
|
|
41 |
|
|
```javascript
|
42 |
|
|
// print-package.js
|
43 |
|
|
const fetch = require('./fetch.js')
|
44 |
|
|
const puddin = require('figgy-pudding')
|
45 |
|
|
|
46 |
|
|
const PrintOpts = puddin({
|
47 |
|
|
json: { default: false }
|
48 |
|
|
})
|
49 |
|
|
|
50 |
|
|
async function printPkg (name, opts) {
|
51 |
|
|
// Expected pattern is to call this in every interface function. If `opts` is
|
52 |
|
|
// not passed in, it will automatically create an (empty) object for it.
|
53 |
|
|
opts = PrintOpts(opts)
|
54 |
|
|
const uri = `https://registry.npmjs.com/${name}`
|
55 |
|
|
const res = await fetch(uri, opts.concat({
|
56 |
|
|
// Add or override any passed-in configs and pass them down.
|
57 |
|
|
log: customLogger
|
58 |
|
|
}))
|
59 |
|
|
// The following would throw an error, because it's not in PrintOpts:
|
60 |
|
|
// console.log(opts.log)
|
61 |
|
|
if (opts.json) {
|
62 |
|
|
return res.json()
|
63 |
|
|
} else {
|
64 |
|
|
return res.text()
|
65 |
|
|
}
|
66 |
|
|
}
|
67 |
|
|
|
68 |
|
|
console.log(await printPkg('figgy', {
|
69 |
|
|
// Pass in *all* configs at the toplevel, as a regular object.
|
70 |
|
|
json: true,
|
71 |
|
|
cache: './tmp-cache'
|
72 |
|
|
}))
|
73 |
|
|
```
|
74 |
|
|
|
75 |
|
|
```javascript
|
76 |
|
|
// fetch.js
|
77 |
|
|
const puddin = require('figgy-pudding')
|
78 |
|
|
|
79 |
|
|
const FetchOpts = puddin({
|
80 |
|
|
log: { default: require('npmlog') },
|
81 |
|
|
cache: {}
|
82 |
|
|
})
|
83 |
|
|
|
84 |
|
|
module.exports = async function (..., opts) {
|
85 |
|
|
opts = FetchOpts(opts)
|
86 |
|
|
}
|
87 |
|
|
```
|
88 |
|
|
|
89 |
|
|
### Features
|
90 |
|
|
|
91 |
|
|
* hide options from layer that didn't ask for it
|
92 |
|
|
* shared multi-layer options
|
93 |
|
|
* make sure `opts` argument is available
|
94 |
|
|
* transparent key access like normal keys, through a Proxy. No need for`.get()`!
|
95 |
|
|
* default values
|
96 |
|
|
* key aliases
|
97 |
|
|
* arbitrary key filter functions
|
98 |
|
|
* key/value iteration
|
99 |
|
|
* serialization
|
100 |
|
|
* 100% test coverage using `tap --100`
|
101 |
|
|
|
102 |
|
|
### API
|
103 |
|
|
|
104 |
|
|
#### <a name="figgy-pudding"></a> `> figgyPudding({ key: { default: val } | String }, [opts]) -> PuddingFactory`
|
105 |
|
|
|
106 |
|
|
Defines an Options constructor that can be used to collect only the needed
|
107 |
|
|
options.
|
108 |
|
|
|
109 |
|
|
An optional `default` property for specs can be used to specify default values
|
110 |
|
|
if nothing was passed in.
|
111 |
|
|
|
112 |
|
|
If the value for a spec is a string, it will be treated as an alias to that
|
113 |
|
|
other key.
|
114 |
|
|
|
115 |
|
|
##### Example
|
116 |
|
|
|
117 |
|
|
```javascript
|
118 |
|
|
const MyAppOpts = figgyPudding({
|
119 |
|
|
lg: 'log',
|
120 |
|
|
log: {
|
121 |
|
|
default: () => require('npmlog')
|
122 |
|
|
},
|
123 |
|
|
cache: {}
|
124 |
|
|
})
|
125 |
|
|
```
|
126 |
|
|
|
127 |
|
|
#### <a name="pudding-factory"></a> `> PuddingFactory(...providers) -> FiggyPudding{}`
|
128 |
|
|
|
129 |
|
|
Instantiates an options object defined by `figgyPudding()`, which uses
|
130 |
|
|
`providers`, in order, to find requested properties.
|
131 |
|
|
|
132 |
|
|
Each provider can be either a plain object, a `Map`-like object (that is, one
|
133 |
|
|
with a `.get()` method) or another figgyPudding `Opts` object.
|
134 |
|
|
|
135 |
|
|
When nesting `Opts` objects, their properties will not become available to the
|
136 |
|
|
new object, but any further nested `Opts` that reference that property _will_ be
|
137 |
|
|
able to read from their grandparent, as long as they define that key. Default
|
138 |
|
|
values for nested `Opts` parents will be used, if found.
|
139 |
|
|
|
140 |
|
|
##### Example
|
141 |
|
|
|
142 |
|
|
```javascript
|
143 |
|
|
const ReqOpts = figgyPudding({
|
144 |
|
|
follow: {}
|
145 |
|
|
})
|
146 |
|
|
|
147 |
|
|
const opts = ReqOpts({
|
148 |
|
|
follow: true,
|
149 |
|
|
log: require('npmlog')
|
150 |
|
|
})
|
151 |
|
|
|
152 |
|
|
opts.follow // => true
|
153 |
|
|
opts.log // => Error: ReqOpts does not define `log`
|
154 |
|
|
|
155 |
|
|
const MoreOpts = figgyPudding({
|
156 |
|
|
log: {}
|
157 |
|
|
})
|
158 |
|
|
MoreOpts(opts).log // => npmlog object (passed in from original plain obj)
|
159 |
|
|
MoreOpts(opts).follow // => Error: MoreOpts does not define `follow`
|
160 |
|
|
```
|
161 |
|
|
|
162 |
|
|
#### <a name="opts-get"></a> `> opts.get(key) -> Value`
|
163 |
|
|
|
164 |
|
|
Gets a value from the options object.
|
165 |
|
|
|
166 |
|
|
##### Example
|
167 |
|
|
|
168 |
|
|
```js
|
169 |
|
|
const opts = MyOpts(config)
|
170 |
|
|
opts.get('foo') // value of `foo`
|
171 |
|
|
opts.foo // Proxy-based access through `.get()`
|
172 |
|
|
```
|
173 |
|
|
|
174 |
|
|
#### <a name="opts-concat"></a> `> opts.concat(...moreProviders) -> FiggyPudding{}`
|
175 |
|
|
|
176 |
|
|
Creates a new opts object of the same type as `opts` with additional providers.
|
177 |
|
|
Providers further to the right shadow providers to the left, with properties in
|
178 |
|
|
the original `opts` being shadows by the new providers.
|
179 |
|
|
|
180 |
|
|
##### Example
|
181 |
|
|
|
182 |
|
|
```js
|
183 |
|
|
const opts = MyOpts({x: 1})
|
184 |
|
|
opts.get('x') // 1
|
185 |
|
|
opts.concat({x: 2}).get('x') // 2
|
186 |
|
|
opts.get('x') // 1 (original opts object left intact)
|
187 |
|
|
```
|
188 |
|
|
|
189 |
|
|
#### <a name="opts-to-json"></a> `> opts.toJSON() -> Value`
|
190 |
|
|
|
191 |
|
|
Converts `opts` to a plain, JSON-stringifiable JavaScript value. Used internally
|
192 |
|
|
by JavaScript to get `JSON.stringify()` working.
|
193 |
|
|
|
194 |
|
|
Only keys that are readable by the current pudding type will be serialized.
|
195 |
|
|
|
196 |
|
|
##### Example
|
197 |
|
|
|
198 |
|
|
```js
|
199 |
|
|
const opts = MyOpts({x: 1})
|
200 |
|
|
opts.toJSON() // {x: 1}
|
201 |
|
|
JSON.stringify(opts) // '{"x":1}'
|
202 |
|
|
```
|
203 |
|
|
|
204 |
|
|
#### <a name="opts-for-each"></a> `> opts.forEach((value, key, opts) => {}, thisArg) -> undefined`
|
205 |
|
|
|
206 |
|
|
Iterates over the values of `opts`, limited to the keys readable by the current
|
207 |
|
|
pudding type. `thisArg` will be used to set the `this` argument when calling the
|
208 |
|
|
`fn`.
|
209 |
|
|
|
210 |
|
|
##### Example
|
211 |
|
|
|
212 |
|
|
```js
|
213 |
|
|
const opts = MyOpts({x: 1, y: 2})
|
214 |
|
|
opts.forEach((value, key) => console.log(key, '=', value))
|
215 |
|
|
```
|
216 |
|
|
|
217 |
|
|
#### <a name="opts-entries"></a> `> opts.entries() -> Iterator<[[key, value], ...]>`
|
218 |
|
|
|
219 |
|
|
Returns an iterator that iterates over the keys and values in `opts`, limited to
|
220 |
|
|
the keys readable by the current pudding type. Each iteration returns an array
|
221 |
|
|
of `[key, value]`.
|
222 |
|
|
|
223 |
|
|
##### Example
|
224 |
|
|
|
225 |
|
|
```js
|
226 |
|
|
const opts = MyOpts({x: 1, y: 2})
|
227 |
|
|
[...opts({x: 1, y: 2}).entries()] // [['x', 1], ['y', 2]]
|
228 |
|
|
```
|
229 |
|
|
|
230 |
|
|
#### <a name="opts-symbol-iterator"></a> `> opts[Symbol.iterator]() -> Iterator<[[key, value], ...]>`
|
231 |
|
|
|
232 |
|
|
Returns an iterator that iterates over the keys and values in `opts`, limited to
|
233 |
|
|
the keys readable by the current pudding type. Each iteration returns an array
|
234 |
|
|
of `[key, value]`. Makes puddings work natively with JS iteration mechanisms.
|
235 |
|
|
|
236 |
|
|
##### Example
|
237 |
|
|
|
238 |
|
|
```js
|
239 |
|
|
const opts = MyOpts({x: 1, y: 2})
|
240 |
|
|
[...opts({x: 1, y: 2})] // [['x', 1], ['y', 2]]
|
241 |
|
|
for (let [key, value] of opts({x: 1, y: 2})) {
|
242 |
|
|
console.log(key, '=', value)
|
243 |
|
|
}
|
244 |
|
|
```
|
245 |
|
|
|
246 |
|
|
#### <a name="opts-keys"></a> `> opts.keys() -> Iterator<[key, ...]>`
|
247 |
|
|
|
248 |
|
|
Returns an iterator that iterates over the keys in `opts`, limited to the keys
|
249 |
|
|
readable by the current pudding type.
|
250 |
|
|
|
251 |
|
|
##### Example
|
252 |
|
|
|
253 |
|
|
```js
|
254 |
|
|
const opts = MyOpts({x: 1, y: 2})
|
255 |
|
|
[...opts({x: 1, y: 2}).keys()] // ['x', 'y']
|
256 |
|
|
```
|
257 |
|
|
|
258 |
|
|
#### <a name="opts-values"></a> `> opts.values() -> Iterator<[value, ...]>`
|
259 |
|
|
|
260 |
|
|
Returns an iterator that iterates over the values in `opts`, limited to the keys
|
261 |
|
|
readable by the current pudding type.
|
262 |
|
|
|
263 |
|
|
##### Example
|
264 |
|
|
'
|
265 |
|
|
```js
|
266 |
|
|
const opts = MyOpts({x: 1, y: 2})
|
267 |
|
|
[...opts({x: 1, y: 2}).values()] // [1, 2]
|
268 |
|
|
```
|