Skip to content

Commit

Permalink
docs(src): add examples
Browse files Browse the repository at this point in the history
Also add several clarifications and regenerate API docs.
  • Loading branch information
richrdkng committed Apr 22, 2019
1 parent d315496 commit fa0757f
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 35 deletions.
142 changes: 114 additions & 28 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
<dd></dd>
<dt><a href="#module_optionist/assign/underscore">optionist/assign/underscore</a></dt>
<dd></dd>
<dt><a href="#module_optionist/process/get">optionist/process/get</a></dt>
<dd></dd>
<dt><a href="#module_optionist/process">optionist/process</a></dt>
<dd></dd>
<dt><a href="#module_optionist/process/get">optionist/process/get</a></dt>
<dd></dd>
</dl>

<a name="module_optionist"></a>
Expand All @@ -24,8 +24,8 @@

### module.exports([options], [defaultOptions]) ⇒ <code>Object</code> ⏏
Copies and merges options and default options into a new object.
If no options and defaultOptions were passed, or they are both null, or falsy,
an empty Object will be returned (e.g.: {}).
If no `options` and `defaultOptions` were passed, or they are both `null`, or falsy,
an empty Object will be returned (e.g.: `{}`).

**Kind**: Exported function
**Returns**: <code>Object</code> - The new object with the merged options.
Expand Down Expand Up @@ -162,19 +162,20 @@ function myFunction (options = null) {
options = process(options, DEFAULTS)

// handle complex, deeply nested Objects without 'Uncaught ReferenceError'
// and constant "key within object" checking, e.g.:
// note: key existence checking isn't needed (e.g.: if (options.settings && 'data' in options.settings && ...))
// and constant "key within object" checking
// note: key existence checking isn't needed (e.g.:
// if (options.settings && 'data' in options.settings && ...) { ... })
this._value = get(options.settings.deeply.nested.data.value)
// note: per-option default option is also possible, when the specific option doesn't exist
this._flag = get(options.settings.burried.deeply.flag, true)
this._flag = get(options.settings.burried.deeply.yet.doesnt.exist.flag, true)

// also possible in conditions...
if (get(options.deeply.nested.settings.value) > 0) {
// handle value
}

// ...with per-option default option, when the specific option doesn't exist
if (get(options.some.other.deeply.nested.flag, false)) {
if (get(options.some.other.deeply.nested.non.existent.flag, false)) {
// handle flag
}
}
Expand Down Expand Up @@ -281,20 +282,19 @@ Processes the given options and assigns them by setting the underscored properti
</tr> </tbody>
</table>

<a name="module_optionist/process/get"></a>
<a name="module_optionist/process"></a>

## optionist/process/get
<a name="exp_module_optionist/process/get--module.exports"></a>
## optionist/process
<a name="exp_module_optionist/process--module.exports"></a>

### module.exports([option], [defaultOption]) ⇒ <code>\*</code> ⏏
Returns the specific option of the processed options from a recursive Proxy.
### module.exports([options], [defaultOptions]) ⇒ <code>Object</code> ⏏
Processes the options and default options and merges them into a new recursive Proxy.
This recursive Proxy provides a convenient and short way to handle complex, deeply nested options
without getting `Uncaught ReferenceError` and constantly checking whether keys exist in objects
(e.g.: `if (options.settings && 'data' in options.settings && ...) { ... }`).

**Kind**: Exported function
**Returns**: <code>\*</code> - The specific option.
**Throws**:

- <code>TypeError</code> In case the option was not previously processed with ".process()".

**Returns**: <code>Object</code> - The new recursive Proxy with the processed options.
<table>
<thead>
<tr>
Expand All @@ -303,24 +303,81 @@ Returns the specific option of the processed options from a recursive Proxy.
</thead>
<tbody>
<tr>
<td>[option]</td><td><code>Object</code></td><td><p>The specific option to return.</p>
<td>[options]</td><td><code>Object</code></td><td><p>The options to use to merge into a new recursive Proxy.</p>
</td>
</tr><tr>
<td>[defaultOption]</td><td><code>Object</code></td><td><p>The default option to return in case the specific option is not present.</p>
<td>[defaultOptions]</td><td><code>Object</code></td><td><p>The default options to use to merge into a new recursive Proxy.</p>
</td>
</tr> </tbody>
</table>

<a name="module_optionist/process"></a>
**Example** *(complex/convenient options object handling with default options)*
```js
// note: when using 'optionist/process', you also need 'optionist/process/get' too
const process = require('optionist/process')
const get = require('optionist/process/get')

## optionist/process
<a name="exp_module_optionist/process--module.exports"></a>
function myFunction (options = null) {
options = process(options, DEFAULTS) // best practice: use a constant, when storing your defaults

### module.exports([options], [defaultOptions]) ⇒ <code>Object</code> ⏏
Processes the options and default options into a new recursive Proxy.
// handle complex, deeply nested Objects without 'Uncaught ReferenceError'
// and constant "key within object" checking
// note: key existence checking isn't needed (e.g.:
// if (options.settings && 'data' in options.settings && ...) { ... })
this._value = get(options.settings.deeply.nested.data.value)
// note: per-option default option is also possible, when the specific option doesn't exist
this._flag = get(options.settings.burried.deeply.yet.doesnt.exist.flag, true)

// also possible in conditions...
if (get(options.deeply.nested.settings.value) > 0) {
// handle value
}

// ...with per-option default option, when the specific option doesn't exist
if (get(options.some.other.deeply.nested.non.existent.flag, false)) {
// handle flag
}
}

// or with a class
class MyClass {
constructor (options = null) {
options = process(options, DEFAULTS) // best practice: use a constant, when storing your defaults

// handle complex, deeply nested Objects without 'Uncaught ReferenceError'
// and constant "key within object" checking
// note: key existence checking isn't needed (e.g.:
// if (options.settings && 'data' in options.settings && ...) { ... })
this._value = get(options.settings.deeply.nested.data.value)
// note: per-option default option is also possible, when the specific option doesn't exist
this._flag = get(options.settings.burried.deeply.yet.doesnt.exist.flag, true)

// also possible in conditions...
if (get(options.deeply.nested.settings.value) > 0) {
// handle value
}

// ...with per-option default option, when the specific option doesn't exist
if (!get(options.some.other.deeply.nested.non.existent.flag, false)) {
// handle flag
}
}
}
```
<a name="module_optionist/process/get"></a>

## optionist/process/get
<a name="exp_module_optionist/process/get--module.exports"></a>

### module.exports([option], [defaultOption]) ⇒ <code>\*</code> ⏏
Returns the specific option of the processed options from a recursive Proxy.

**Kind**: Exported function
**Returns**: <code>Object</code> - The new recursive Proxy with the processed options.
**Returns**: <code>\*</code> - The specific option.
**Throws**:

- <code>TypeError</code> In case the option was not previously processed with ".process()".

<table>
<thead>
<tr>
Expand All @@ -329,11 +386,40 @@ Processes the options and default options into a new recursive Proxy.
</thead>
<tbody>
<tr>
<td>[options]</td><td><code>Object</code></td><td><p>The options to use to merge into a new recursive Proxy.</p>
<td>[option]</td><td><code>Object</code></td><td><p>The specific option to return.</p>
</td>
</tr><tr>
<td>[defaultOptions]</td><td><code>Object</code></td><td><p>The default options to use to merge into a new recursive Proxy.</p>
<td>[defaultOption]</td><td><code>Object</code></td><td><p>The default option to return in case the specific option is not present.</p>
</td>
</tr> </tbody>
</table>

**Example** *(get the processed options - for more examples, check: **optionist/process**)*
```js
const process = require('optionist/process')
const get = require('optionist/process/get')

class MyClass {
constructor (options = null) {
options = process(options, DEFAULTS)

// handle complex, deeply nested Objects without 'Uncaught ReferenceError'
// and constant "key within object" checking
// note: key existence checking isn't needed (e.g.:
// if (options.settings && 'data' in options.settings && ...) { ... })
this._value = get(options.settings.deeply.nested.data.value)
// note: per-option default option is also possible, when the specific option doesn't exist
this._flag = get(options.settings.burried.deeply.yet.doesnt.exist.flag, true)

// also possible in conditions...
if (get(options.deeply.nested.settings.value) > 0) {
// handle value
}

// ...with per-option default option, when the specific option doesn't exist
if (!get(options.some.other.deeply.nested.non.existent.flag, false)) {
// handle flag
}
}
}
```
13 changes: 7 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ const merge = require('./_utils/_merge')

/**
* Copies and merges options and default options into a new object.
* If no options and defaultOptions were passed, or they are both null, or falsy,
* an empty Object will be returned (e.g.: {}).
* If no `options` and `defaultOptions` were passed, or they are both `null`, or falsy,
* an empty Object will be returned (e.g.: `{}`).
*
* @param {Object} [options] - The options to use to merge into a new object.
* @param {Object} [defaultOptions] - The default options to use to merge into a new object.
Expand Down Expand Up @@ -128,19 +128,20 @@ const merge = require('./_utils/_merge')
* options = process(options, DEFAULTS)
*
* // handle complex, deeply nested Objects without 'Uncaught ReferenceError'
* // and constant "key within object" checking, e.g.:
* // note: key existence checking isn't needed (e.g.: if (options.settings && 'data' in options.settings && ...))
* // and constant "key within object" checking
* // note: key existence checking isn't needed (e.g.:
* // if (options.settings && 'data' in options.settings && ...) { ... })
* this._value = get(options.settings.deeply.nested.data.value)
* // note: per-option default option is also possible, when the specific option doesn't exist
* this._flag = get(options.settings.burried.deeply.flag, true)
* this._flag = get(options.settings.burried.deeply.yet.doesnt.exist.flag, true)
*
* // also possible in conditions...
* if (get(options.deeply.nested.settings.value) > 0) {
* // handle value
* }
*
* // ...with per-option default option, when the specific option doesn't exist
* if (get(options.some.other.deeply.nested.flag, false)) {
* if (get(options.some.other.deeply.nested.non.existent.flag, false)) {
* // handle flag
* }
* }
Expand Down
28 changes: 28 additions & 0 deletions src/process/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,34 @@ function resetKey (proxy) {
* @returns {*} The specific option.
*
* @throws {TypeError} In case the option was not previously processed with ".process()".
*
* @example <caption>get the processed options - for more examples, check: **optionist/process**</caption>
* const process = require('optionist/process')
* const get = require('optionist/process/get')
*
* class MyClass {
* constructor (options = null) {
* options = process(options, DEFAULTS)
*
* // handle complex, deeply nested Objects without 'Uncaught ReferenceError'
* // and constant "key within object" checking
* // note: key existence checking isn't needed (e.g.:
* // if (options.settings && 'data' in options.settings && ...) { ... })
* this._value = get(options.settings.deeply.nested.data.value)
* // note: per-option default option is also possible, when the specific option doesn't exist
* this._flag = get(options.settings.burried.deeply.yet.doesnt.exist.flag, true)
*
* // also possible in conditions...
* if (get(options.deeply.nested.settings.value) > 0) {
* // handle value
* }
*
* // ...with per-option default option, when the specific option doesn't exist
* if (!get(options.some.other.deeply.nested.non.existent.flag, false)) {
* // handle flag
* }
* }
* }
*/
module.exports = (option = null, defaultOption = null) => {
if (!option || typeof option !== 'object') {
Expand Down
57 changes: 56 additions & 1 deletion src/process/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,67 @@ const KEYS = require('../_utils/_KEYS')
const merge = require('../_utils/_merge')

/**
* Processes the options and default options into a new recursive Proxy.
* Processes the options and default options and merges them into a new recursive Proxy.
* This recursive Proxy provides a convenient and short way to handle complex, deeply nested options
* without getting `Uncaught ReferenceError` and constantly checking whether keys exist in objects
* (e.g.: `if (options.settings && 'data' in options.settings && ...) { ... }`).
*
* @param {Object} [options] - The options to use to merge into a new recursive Proxy.
* @param {Object} [defaultOptions] - The default options to use to merge into a new recursive Proxy.
*
* @returns {Object} The new recursive Proxy with the processed options.
*
* @example <caption>complex/convenient options object handling with default options</caption>
* // note: when using 'optionist/process', you also need 'optionist/process/get' too
* const process = require('optionist/process')
* const get = require('optionist/process/get')
*
* function myFunction (options = null) {
* options = process(options, DEFAULTS) // best practice: use a constant, when storing your defaults
*
* // handle complex, deeply nested Objects without 'Uncaught ReferenceError'
* // and constant "key within object" checking
* // note: key existence checking isn't needed (e.g.:
* // if (options.settings && 'data' in options.settings && ...) { ... })
* this._value = get(options.settings.deeply.nested.data.value)
* // note: per-option default option is also possible, when the specific option doesn't exist
* this._flag = get(options.settings.burried.deeply.yet.doesnt.exist.flag, true)
*
* // also possible in conditions...
* if (get(options.deeply.nested.settings.value) > 0) {
* // handle value
* }
*
* // ...with per-option default option, when the specific option doesn't exist
* if (get(options.some.other.deeply.nested.non.existent.flag, false)) {
* // handle flag
* }
* }
*
* // or with a class
* class MyClass {
* constructor (options = null) {
* options = process(options, DEFAULTS) // best practice: use a constant, when storing your defaults
*
* // handle complex, deeply nested Objects without 'Uncaught ReferenceError'
* // and constant "key within object" checking
* // note: key existence checking isn't needed (e.g.:
* // if (options.settings && 'data' in options.settings && ...) { ... })
* this._value = get(options.settings.deeply.nested.data.value)
* // note: per-option default option is also possible, when the specific option doesn't exist
* this._flag = get(options.settings.burried.deeply.yet.doesnt.exist.flag, true)
*
* // also possible in conditions...
* if (get(options.deeply.nested.settings.value) > 0) {
* // handle value
* }
*
* // ...with per-option default option, when the specific option doesn't exist
* if (!get(options.some.other.deeply.nested.non.existent.flag, false)) {
* // handle flag
* }
* }
* }
*/
module.exports = (options = null, defaultOptions = null) => {
// create a recursive Proxy with Symbol-based keys to store data
Expand Down

0 comments on commit fa0757f

Please sign in to comment.