Browse Source

[merge] #2 from codefeathers/develop

Major rewrite to `Fuse`

Added new utilities and exposed FuseIterable:

* Fuse.on
* Fuse.is
* Fuse.not
* Fuse.resolve
* FuseIterable.on
* FuseIterable.onField
* Fuse.resolve
master
Muthu Kumar 7 years ago
committed by GitHub
parent
commit
f2fb4dadd0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 24
      README.md
  2. 139
      Select.js
  3. 840
      docs/Fuse.html
  4. 593
      docs/FuseItem.html
  5. 844
      docs/FuseIterable.html
  6. 474
      docs/global.html
  7. 29
      docs/index.html
  8. 233
      docs/index.js.html
  9. 182
      index.js
  10. 16
      package.json
  11. 87
      spec/Fuse-spec.js
  12. 44
      spec/FuseIterable-spec.js
  13. 24
      spec/SelectArraySpec.js
  14. 51
      spec/SelectSpec.js

24
README.md

@ -1,18 +1,22 @@
# select-return
# Fuse
**FunctionSelect**
Return a function based on a condition. Functional alternative to switch-case.
`Fuse` selects a function that passes a condition.
## Usage
```JavaScript
const Fuse = require('@codefeathers/fuse');
const { FuseIterable } = require('@codefeathers/fuse');
const a = 100;
const result = new Select(a)
.for(x => x>10,
const result = new Fuse(a)
.on(x => x>10,
a => `${a} is greater than 10.`)
.for(x => x<10,
.on(x => x<10,
a => `${a} is lesser than 10.`)
.for(x => x===10,
.on(x => x===10,
a => `${a} is 10.`)
console.log(result.resolve()); // -> "100 is greater than 10."
@ -24,17 +28,15 @@ Docs exist in `/docs` directory. Will be served soon.
## Development
> If you find any mistakes in code/documentation, or if you feel something could be done better, do PR :)
> I appreciate it.
> If you find any mistakes in code/documentation, or if you feel something could be done better, do PR :) I appreciate it.
- Always write test spec for any code you add. Make sure they run as intended.
- Add/update JSDoc comments as needed.
- Use npm scripts for linting, debugging, building docs.
- Use npm scripts for linting, tests, debugging, building docs.
Place your test file as `testscript.js` in root.
The following npm scripts are available: `npm run lint`, `npm run debug`, `npm run docs`.
The following npm scripts are available: `npm run lint`, `npm test`, `npm run debug`, `npm run docs`.
## Credits

139
Select.js

@ -1,139 +0,0 @@
'use strict';
/**
* Return a function based on a condition.
* Functional alternative to switch-case.
* @projectname Select-Return
* @version 1.0.0
* @author Muthu Kumar (@MKRhere)
*/
/**
* Creates a SelectValue instance with a value and optional resolve function.
* Created internally from SelectIterable constructor, and not exported.
* @class SelectValue
*/
class SelectValue {
/**
* @param {any} value - the input value
* @param {function} resolve - optional resolve function
* @constructs SelectIterable
*/
constructor(value, resolve) {
this.value = value;
if (resolve) this.resolve = (...args) => resolve(...args, value);
}
/**
* Default resolve prototype. Returns null when called.
* Used in case a resolve is never set.
* @returns {object} null
* @memberof SelectValue
*/
resolve() {
return null;
}
}
/**
* Creates a SelectIterable instance from an array.
* Created internally from Select.prototype.for, and not exported.
* @class SelectIterable
*/
class SelectIterable {
/**
* @param {array} values - array created from Select.prototype.for
* @param {Array<function>} tests - array of { test, consequent } objects
* @param {function} tests[].test - test function
* @param {function} tests[].consequent - consequent function
* @constructs SelectIterable
*/
constructor(values, tests) {
this.values = values
.map(x => x instanceof SelectValue
? x
: new SelectValue(x)
);
this.tests = tests;
}
/**
* Accepts a test and consequent function each and returns a new
* SelectIterable instance.
* @param {Test} test - test callback function
* @param {function} consequent - consequent callback function
* @returns {SelectIterable} - an instance of SelectIterable
* @memberof SelectIterable
*/
for(test, consequent) {
/* SelectIterable.prototype.for works a little
differently than Select.prototype.for,
by accumulating the tests and resolving
all the values when .resolve() is called */
return new SelectIterable(
this.values,
[ ...this.tests, { test, consequent } ]
);
}
resolve(...args) {
/* When .resolve() is called, a resolved value
is generated for each value in the array */
return this.values.map(item => {
const resolver = this
.tests
.find(x => x.test(item.value)
? x.consequent
: null);
return resolver
? resolver.consequent(...args, item.value)
: null;
});
}
}
/**
* Creates a new Select instance.
* @class Select
* @extends {SelectValue}
*/
class Select extends SelectValue {
/**
* @param {any|array} value - the value or array of values to check against
* @param {function} resolve - optional resolve function
* @constructs Select
*/
constructor(value, resolve) {
super(value, resolve);
this.iterable = typeof value === "object" && Symbol.iterator in value;
}
/**
* Accepts a test and consequent function each and returns a new
* Select or SelectIterable instance.
* @param {function} test - test callback function
* @param {function} consequent - consequent callback function
* @returns {Select|SelectIterable} - Returns a SelectIterable instance
* if value was array, or a Select instance otherwise
* @memberof Select
*/
for(test, consequent) {
if (this.iterable) {
/* If the value passed to the constructor is
an array, initialise a new SelectIterable
with the array and { test, consequent } pair
and return */
return new SelectIterable(
Array.from(this.value),
[ { test, consequent } ],
);
}
if (test(this.value)) return new Select(this.value, consequent);
/* If the test doesn't pass, just pass the Select
instance along the chain until a test passes,
or .resolve() is called */
return this;
}
}
module.exports = Select;

840
docs/Fuse.html

@ -0,0 +1,840 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: Fuse</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Class: Fuse</h1>
<section>
<header>
<h2><span class="attribs"><span class="type-signature"></span></span>Fuse<span class="signature">()</span><span class="type-signature"></span></h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="Fuse"><span class="type-signature"></span>new Fuse<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
Creates a new Fuse instance.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line128">line 128</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Extends</h3>
<ul>
<li><a href="FuseItem.html">FuseItem</a></li>
</ul>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="is"><span class="type-signature"></span>is<span class="signature">(value, consequent)</span><span class="type-signature"> &rarr; {<a href="Fuse.html">Fuse</a>}</span></h4>
<div class="description">
Accepts a value instead of a test function, and checks for strict
equality with this.value.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>value</code></td>
<td class="type">
<span class="param-type">any</span>
</td>
<td class="description last">Any value to check against this.value</td>
</tr>
<tr>
<td class="name"><code>consequent</code></td>
<td class="type">
<span class="param-type">function</span>
</td>
<td class="description last">Consequent callback function</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line164">line 164</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
An instance of Fuse
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="Fuse.html">Fuse</a></span>
</dd>
</dl>
<h4 class="name" id="not"><span class="type-signature"></span>not<span class="signature">(value, consequent)</span><span class="type-signature"> &rarr; {<a href="Fuse.html">Fuse</a>}</span></h4>
<div class="description">
Accepts a value instead of a test function, and checks for strict
inequality with this.value.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>value</code></td>
<td class="type">
<span class="param-type">any</span>
</td>
<td class="description last">Any value to check against this.value</td>
</tr>
<tr>
<td class="name"><code>consequent</code></td>
<td class="type">
<span class="param-type">function</span>
</td>
<td class="description last">Consequent callback function</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line176">line 176</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
An instance of Fuse
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="Fuse.html">Fuse</a></span>
</dd>
</dl>
<h4 class="name" id="on"><span class="type-signature"></span>on<span class="signature">(predicate, consequent)</span><span class="type-signature"> &rarr; {<a href="Fuse.html">Fuse</a>}</span></h4>
<div class="description">
Accepts a test and consequent function each and returns a new
Fuse or FuseIterable instance.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>predicate</code></td>
<td class="type">
<span class="param-type">callback</span>
</td>
<td class="description last">A test callback function</td>
</tr>
<tr>
<td class="name"><code>consequent</code></td>
<td class="type">
<span class="param-type">callback</span>
</td>
<td class="description last">Consequent callback function</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line143">line 143</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
Returns a new Fuse instance
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="Fuse.html">Fuse</a></span>
</dd>
</dl>
<h4 class="name" id="resolve"><span class="type-signature"></span>resolve<span class="signature">()</span><span class="type-signature"> &rarr; {null}</span></h4>
<div class="description">
Fallback resolve prototype. Returns null when called.
Used in case a resolve is never found.
</div>
<dl class="details">
<dt class="inherited-from">Inherited From:</dt>
<dd class="inherited-from"><ul class="dummy"><li>
<a href="FuseItem.html#resolve">FuseItem#resolve</a>
</li></ul></dd>
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line49">line 49</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
null
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">null</span>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Fuse.html">Fuse</a></li><li><a href="FuseItem.html">FuseItem</a></li><li><a href="FuseIterable.html">FuseIterable</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Apr 11 2018 11:02:55 GMT+0530 (IST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

593
docs/FuseItem.html

@ -0,0 +1,593 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: FuseItem</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Class: FuseItem</h1>
<section>
<header>
<h2><span class="attribs"><span class="type-signature"></span></span>FuseItem<span class="signature">()</span><span class="type-signature"></span></h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="FuseItem"><span class="type-signature"></span>new FuseItem<span class="signature">()</span><span class="type-signature"></span></h4>
<div class="description">
Creates a FuseItem instance with a value and optional resolve function.
FuseIterable constructor uses it internally, and Fuse extends FuseItem.
Not exposed.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="resolve"><span class="type-signature"></span>resolve<span class="signature">()</span><span class="type-signature"> &rarr; {null}</span></h4>
<div class="description">
Fallback resolve prototype. Returns null when called.
Used in case a resolve is never found.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line49">line 49</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
null
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">null</span>
</dd>
</dl>
</article>
</section>
<section>
<header>
<h2><span class="attribs"><span class="type-signature"></span></span>FuseItem<span class="signature">(value, resolve)</span><span class="type-signature"></span></h2>
</header>
<article>
<div class="container-overview">
<h4 class="name" id="FuseItem"><span class="type-signature"></span>new FuseItem<span class="signature">(value, resolve)</span><span class="type-signature"></span></h4>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>value</code></td>
<td class="type">
<span class="param-type">any</span>
</td>
<td class="description last">The input value</td>
</tr>
<tr>
<td class="name"><code>resolve</code></td>
<td class="type">
<span class="param-type">function</span>
</td>
<td class="description last">Optional resolve function</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line35">line 35</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="resolve"><span class="type-signature"></span>resolve<span class="signature">()</span><span class="type-signature"> &rarr; {null}</span></h4>
<div class="description">
Fallback resolve prototype. Returns null when called.
Used in case a resolve is never found.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line49">line 49</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
null
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">null</span>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Fuse.html">Fuse</a></li><li><a href="FuseItem.html">FuseItem</a></li><li><a href="FuseIterable.html">FuseIterable</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Apr 11 2018 11:02:55 GMT+0530 (IST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

844
docs/FuseIterable.html

@ -0,0 +1,844 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: FuseIterable</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Class: FuseIterable</h1>
<section>
<header>
<h2><span class="attribs"><span class="type-signature"></span></span>FuseIterable<span class="signature">(values, tests)</span><span class="type-signature"></span></h2>
<div class="class-description">FuseIterable</div>
</header>
<article>
<div class="container-overview">
<h2>Constructor</h2>
<h4 class="name" id="FuseIterable"><span class="type-signature"></span>new FuseIterable<span class="signature">(values, tests)</span><span class="type-signature"></span></h4>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>values</code></td>
<td class="type">
<span class="param-type">iterable</span>
</td>
<td class="description last">An iterable expression as the switch</td>
</tr>
<tr>
<td class="name"><code>tests</code></td>
<td class="type">
<span class="param-type">Array.&lt;function()></span>
</td>
<td class="description last">Array of { test, consequent } objects
<h6>Properties</h6>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>predicate</code></td>
<td class="type">
<span class="param-type">function</span>
</td>
<td class="description last">Test function</td>
</tr>
<tr>
<td class="name"><code>consequent</code></td>
<td class="type">
<span class="param-type">function</span>
</td>
<td class="description last">Consequent function</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line63">line 63</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<h4 class="name" id="on"><span class="type-signature"></span>on<span class="signature">(predicate, consequent)</span><span class="type-signature"> &rarr; {<a href="FuseIterable.html">FuseIterable</a>}</span></h4>
<div class="description">
Accepts a test and consequent function each and returns a new
FuseIterable instance.
FuseIterable.prototype.for works a little differently than
Fuse.prototype.for, by lazy accumulating the tests and
resolving all the values when .resolve() is called.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>predicate</code></td>
<td class="type">
<span class="param-type">callback</span>
</td>
<td class="description last">A test callback function</td>
</tr>
<tr>
<td class="name"><code>consequent</code></td>
<td class="type">
<span class="param-type">callback</span>
</td>
<td class="description last">Consequent callback function</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line83">line 83</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
An instance of FuseIterable
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="FuseIterable.html">FuseIterable</a></span>
</dd>
</dl>
<h4 class="name" id="onField"><span class="type-signature"></span>onField<span class="signature">(&hellip;tuples)</span><span class="type-signature"> &rarr; {<a href="FuseIterable.html">FuseIterable</a>}</span></h4>
<div class="description">
Accepts a list of tuples as arguments and returns a new
FuseIterable instance. An alternative to chaining multiple
FuseIterable.prototype.on methods.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>tuples</code></td>
<td class="type">
<span class="param-type">Array.&lt;function()></span>
</td>
<td class="attributes">
&lt;repeatable><br>
</td>
<td class="description last">Array of [ predicate, consequent ] pairs</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line99">line 99</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
An instance of FuseIterable
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type"><a href="FuseIterable.html">FuseIterable</a></span>
</dd>
</dl>
<h4 class="name" id="resolve"><span class="type-signature"></span>resolve<span class="signature">(&hellip;args)</span><span class="type-signature"> &rarr; {any|null}</span></h4>
<div class="description">
Accepts parameters during resolve time and passes them along with
each value into the winning consequent function.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>args</code></td>
<td class="type">
<span class="param-type">any</span>
</td>
<td class="attributes">
&lt;repeatable><br>
</td>
<td class="description last">Any number of arguments</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line114">line 114</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
Resolved value or null if it was unresolved
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">any</span>
|
<span class="param-type">null</span>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Fuse.html">Fuse</a></li><li><a href="FuseItem.html">FuseItem</a></li><li><a href="FuseIterable.html">FuseIterable</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Apr 11 2018 11:02:55 GMT+0530 (IST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

474
docs/global.html

@ -0,0 +1,474 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Global</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Global</h1>
<section>
<header>
<h2></h2>
</header>
<article>
<div class="container-overview">
<dl class="details">
</dl>
</div>
<h3 class="subsection-title">Type Definitions</h3>
<h4 class="name" id="consequent"><span class="type-signature"></span>consequent<span class="signature">(value, &hellip;args)</span><span class="type-signature"> &rarr; {any}</span></h4>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Attributes</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>value</code></td>
<td class="type">
<span class="param-type">any</span>
</td>
<td class="attributes">
</td>
<td class="description last">The selected Fuse value</td>
</tr>
<tr>
<td class="name"><code>args</code></td>
<td class="type">
<span class="param-type">any</span>
</td>
<td class="attributes">
&lt;repeatable><br>
</td>
<td class="description last">An arbitrary array of arguments</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line16">line 16</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">any</span>
</dd>
</dl>
<h4 class="name" id="predicate"><span class="type-signature"></span>predicate<span class="signature">(value)</span><span class="type-signature"> &rarr; {boolean}</span></h4>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>value</code></td>
<td class="type">
<span class="param-type">any</span>
</td>
<td class="description last">The selected Fuse value</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="index.js.html">index.js</a>, <a href="index.js.html#line10">line 10</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
The Boolean result of the test
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">boolean</span>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Fuse.html">Fuse</a></li><li><a href="FuseItem.html">FuseItem</a></li><li><a href="FuseIterable.html">FuseIterable</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Apr 11 2018 11:02:55 GMT+0530 (IST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

29
docs/index.html

@ -43,31 +43,32 @@
<section>
<article><h1>select-return</h1><p>Return a function based on a condition. Functional alternative to switch-case.</p>
<h2>Usage</h2><pre class="prettyprint source lang-JavaScript"><code>const a = 100;
<article><h1>Fuse</h1><p><strong>FunctionSelect</strong></p>
<p><code>Fuse</code> selects a function that passes a condition.</p>
<h2>Usage</h2><pre class="prettyprint source lang-JavaScript"><code>const Fuse = require('@codefeathers/fuse');
const { FuseIterable } = require('@codefeathers/fuse');
const result = new Select(a)
.for(x => x>10,
const a = 100;
const result = new Fuse(a)
.on(x => x>10,
a => `${a} is greater than 10.`)
.for(x => x&lt;10,
.on(x => x&lt;10,
a => `${a} is lesser than 10.`)
.for(x => x===10,
.on(x => x===10,
a => `${a} is 10.`)
console.log(result.resolve()); // -> &quot;100 is greater than 10.&quot;</code></pre><h2>Docs</h2><p>Docs exist in <code>/docs</code> directory. Will be served soon.</p>
<h2>Development</h2><blockquote>
<p>If you find any mistakes in code/documentation, or if you feel something could be done better, do PR :)</p>
</blockquote>
<blockquote>
<p>I appreciate it.</p>
<p>If you find any mistakes in code/documentation, or if you feel something could be done better, do PR :) I appreciate it.</p>
</blockquote>
<ul>
<li>Always write test spec for any code you add. Make sure they run as intended.</li>
<li>Add/update JSDoc comments as needed.</li>
<li>Use npm scripts for linting, debugging, building docs.</li>
<li>Use npm scripts for linting, tests, debugging, building docs.</li>
</ul>
<p>Place your test file as <code>testscript.js</code> in root.</p>
<p>The following npm scripts are available: <code>npm run lint</code>, <code>npm run debug</code>, <code>npm run docs</code>.</p>
<p>The following npm scripts are available: <code>npm run lint</code>, <code>npm test</code>, <code>npm run debug</code>, <code>npm run docs</code>.</p>
<h2>Credits</h2><p><a href="https://github.com/Floofies">@Floofies</a> was of huge help during development of this module.</p>
<p>Also, <a href="https://github.com/trgwii">@TRGWII</a> was a source of inspiration and guidance.</p></article>
</section>
@ -80,13 +81,13 @@ console.log(result.resolve()); // -> &quot;100 is greater than 10.&quot;</code><
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Select.html">Select</a></li><li><a href="SelectIterable.html">SelectIterable</a></li><li><a href="SelectValue.html">SelectValue</a></li></ul>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Fuse.html">Fuse</a></li><li><a href="FuseItem.html">FuseItem</a></li><li><a href="FuseIterable.html">FuseIterable</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Tue Apr 10 2018 04:36:07 GMT+0530 (IST)
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Apr 11 2018 11:02:55 GMT+0530 (IST)
</footer>
<script> prettyPrint(); </script>

233
docs/index.js.html

@ -0,0 +1,233 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: index.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: index.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>'use strict';
/**
* FUSE
* FunctionSelect: Return a function based on a condition.
* @version 0.10.0
* @author Muthu Kumar (MKRhere)
*/
/**
* @callback predicate
* @param {any} value The selected Fuse value
* @returns {boolean} The Boolean result of the test
*/
/**
* @callback consequent
* @param {any} value The selected Fuse value
* @param {...any} args An arbitrary array of arguments
* @returns {any}
*/
/**
* Creates a FuseItem instance with a value and optional resolve function.
* FuseIterable constructor uses it internally, and Fuse extends FuseItem.
* Not exposed.
* @class FuseItem
*/
class FuseItem {
/**
* @param {any} value The input value
* @param {function} resolve Optional resolve function
* @constructs FuseItem
*/
constructor(value, resolve) {
this.value = value;
if (resolve) {
this.resolve = (...args) => resolve(this.value, ...args);
this.resolved = true;
}
}
/**
* Fallback resolve prototype. Returns null when called.
* Used in case a resolve is never found.
* @returns {null} null
* @memberof FuseItem
*/
resolve() {
return null;
}
}
/**
* Creates a FuseIterable instance from an array or iterable.
* @class FuseIterable
* @param {iterable} values An iterable expression as the switch
* @param {Array&lt;function>} tests Array of { test, consequent } objects
* @param {function} tests[].predicate Test function
* @param {function} tests[].consequent Consequent function
* @constructs FuseIterable
*/
class FuseIterable {
constructor(values, conditionals) {
this.values = Array.from(values).map(value =>
value instanceof FuseItem
? value
: new FuseItem(value));
this.conditionals = conditionals || [];
}
/**
* Accepts a test and consequent function each and returns a new
* FuseIterable instance.
* FuseIterable.prototype.for works a little differently than
* Fuse.prototype.for, by lazy accumulating the tests and
* resolving all the values when .resolve() is called.
* @param {callback} predicate A test callback function
* @param {callback} consequent Consequent callback function
* @returns {FuseIterable} An instance of FuseIterable
* @memberof FuseIterable
*/
on(predicate, consequent) {
return new FuseIterable(this.values, [
...this.conditionals,
{ predicate, consequent }
]);
}
/**
* Accepts a list of tuples as arguments and returns a new
* FuseIterable instance. An alternative to chaining multiple
* FuseIterable.prototype.on methods.
* @memberOf FuseIterable
* @param {...Array.&lt;function>} tuples -
* Array of [ predicate, consequent ] pairs
* @returns {FuseIterable} An instance of FuseIterable
*/
onField(...tuples) {
const conditionals = tuples.map(conditional =>
({
predicate: conditional[0],
consequent: conditional[1]
}));
return new FuseIterable(this.values, conditionals);
}
/**
* Accepts parameters during resolve time and passes them along with
* each value into the winning consequent function.
* @param {...any} args Any number of arguments
* @returns {(any|null)} Resolved value or null if it was unresolved
*/
resolve(...args) {
return this.values.map(item => {
const resolver = this.conditionals.find(conditional =>
conditional.predicate(item.value)
? conditional.consequent
: null
);
return resolver
? resolver.consequent(item.value, ...args)
: null;
});
}
}
/**
* Creates a new Fuse instance.
* @class Fuse
* @extends {FuseItem}
*/
class Fuse extends FuseItem {
/**
* Accepts a test and consequent function each and returns a new
* Fuse or FuseIterable instance.
* @param {callback} predicate A test callback function
* @param {callback} consequent Consequent callback function
* @returns {Fuse} Returns a new Fuse instance
* @memberof Fuse
*/
on(predicate, consequent) {
/* If a resolve exists, just pass on the instance
until .resolve() is called */
if (this.resolved) return this;
if (predicate(this.value)) return new Fuse(this.value, consequent);
/* If the test doesn't pass, just pass the Fuse
instance along the chain until a test passes,
or .resolve() is called */
return this;
}
/**
* Accepts a value instead of a test function, and checks for strict
* equality with this.value.
* @param {any} value Any value to check against this.value
* @param {function} consequent Consequent callback function
* @returns {Fuse} An instance of Fuse
*/
is(value, consequent) {
return this.on(() => value === this.value, consequent);
}
/**
* Accepts a value instead of a test function, and checks for strict
* inequality with this.value.
* @param {any} value Any value to check against this.value
* @param {function} consequent Consequent callback function
* @returns {Fuse} An instance of Fuse
*/
not(value, consequent) {
return this.on(() => value !== this.value, consequent);
}
}
module.exports = Fuse;
module.exports.FuseIterable = FuseIterable;
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Fuse.html">Fuse</a></li><li><a href="FuseItem.html">FuseItem</a></li><li><a href="FuseIterable.html">FuseIterable</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Apr 11 2018 11:02:55 GMT+0530 (IST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

182
index.js

@ -0,0 +1,182 @@
'use strict';
/**
* FUSE
* FunctionSelect: Return a function based on a condition.
* @version 0.10.0
* @author Muthu Kumar (MKRhere)
*/
/**
* @callback predicate
* @param {any} value The selected Fuse value
* @returns {boolean} The Boolean result of the test
*/
/**
* @callback consequent
* @param {any} value The selected Fuse value
* @param {...any} args An arbitrary array of arguments
* @returns {any}
*/
/**
* Creates a FuseItem instance with a value and optional resolve function.
* FuseIterable constructor uses it internally, and Fuse extends FuseItem.
* Not exposed.
* @class FuseItem
*/
class FuseItem {
/**
* @param {any} value The input value
* @param {function} resolve Optional resolve function
* @constructs FuseItem
*/
constructor(value, resolve) {
this.value = value;
if (resolve) {
this.resolve = (...args) => resolve(this.value, ...args);
this.resolved = true;
}
}
/**
* Fallback resolve prototype. Returns null when called.
* Used in case a resolve is never found.
* @returns {null} null
* @memberof FuseItem
*/
resolve() {
return null;
}
}
/**
* Creates a FuseIterable instance from an array or iterable.
* @class FuseIterable
* @param {iterable} values An iterable expression as the switch
* @param {Array<function>} tests Array of { test, consequent } objects
* @param {function} tests[].predicate Test function
* @param {function} tests[].consequent Consequent function
* @constructs FuseIterable
*/
class FuseIterable {
constructor(values, conditionals) {
this.values = Array.from(values).map(value =>
value instanceof FuseItem
? value
: new FuseItem(value));
this.conditionals = conditionals || [];
}
/**
* Accepts a test and consequent function each and returns a new
* FuseIterable instance.
* FuseIterable.prototype.for works a little differently than
* Fuse.prototype.for, by lazy accumulating the tests and
* resolving all the values when .resolve() is called.
* @param {callback} predicate A test callback function
* @param {callback} consequent Consequent callback function
* @returns {FuseIterable} An instance of FuseIterable
* @memberof FuseIterable
*/
on(predicate, consequent) {
return new FuseIterable(this.values, [
...this.conditionals,
{ predicate, consequent }
]);
}
/**
* Accepts a list of tuples as arguments and returns a new
* FuseIterable instance. An alternative to chaining multiple
* FuseIterable.prototype.on methods.
* @memberOf FuseIterable
* @param {...Array.<function>} tuples -
* Array of [ predicate, consequent ] pairs
* @returns {FuseIterable} An instance of FuseIterable
*/
onField(...tuples) {
const conditionals = tuples.map(conditional =>
({
predicate: conditional[0],
consequent: conditional[1]
}));
return new FuseIterable(this.values, conditionals);
}
/**
* Accepts parameters during resolve time and passes them along with
* each value into the winning consequent function.
* @param {...any} args Any number of arguments
* @returns {(any|null)} Resolved value or null if it was unresolved
*/
resolve(...args) {
return this.values.map(item => {
const resolver = this.conditionals.find(conditional =>
conditional.predicate(item.value)
? conditional.consequent
: null
);
return resolver
? resolver.consequent(item.value, ...args)
: null;
});
}
}
/**
* Creates a new Fuse instance.
* @class Fuse
* @extends {FuseItem}
*/
class Fuse extends FuseItem {
/**
* Accepts a test and consequent function each and returns a new
* Fuse or FuseIterable instance.
* @param {callback} predicate A test callback function
* @param {callback} consequent Consequent callback function
* @returns {Fuse} Returns a new Fuse instance
* @memberof Fuse
*/
on(predicate, consequent) {
/* If a resolve exists, just pass on the instance
until .resolve() is called */
if (this.resolved) return this;
if (predicate(this.value)) return new Fuse(this.value, consequent);
/* If the test doesn't pass, just pass the Fuse
instance along the chain until a test passes,
or .resolve() is called */
return this;
}
/**
* Accepts a value instead of a test function, and checks for strict
* equality with this.value.
* @param {any} value Any value to check against this.value
* @param {function} consequent Consequent callback function
* @returns {Fuse} An instance of Fuse
*/
is(value, consequent) {
return this.on(() => value === this.value, consequent);
}
/**
* Accepts a value instead of a test function, and checks for strict
* inequality with this.value.
* @param {any} value Any value to check against this.value
* @param {function} consequent Consequent callback function
* @returns {Fuse} An instance of Fuse
*/
not(value, consequent) {
return this.on(() => value !== this.value, consequent);
}
}
module.exports = Fuse;
module.exports.FuseIterable = FuseIterable;

16
package.json

@ -1,19 +1,21 @@
{
"name": "select-return",
"version": "0.0.9",
"name": "@codefeathers/fuse",
"version": "0.10.0",
"description": "Return a function based on a condition. A functional alternative to switch-case.",
"main": "Select.js",
"main": "index.js",
"scripts": {
"debug": "node --inspect-brk testscript",
"lint": "npx eslint .",
"test": "npx jasmine",
"docs": "npx jsdoc Select.js README.md --destination docs"
"docs": "npx jsdoc index.js README.md --destination docs"
},
"repository": {
"type": "git",
"url": "git+https://github.com/codefeathers/select-return.git"
"url": "git+https://github.com/codefeathers/Fuse.git"
},
"keywords": [
"fuse",
"function",
"select",
"return",
"switch-case",
@ -25,9 +27,9 @@
],
"license": "MIT",
"bugs": {
"url": "https://github.com/codefeathers/select-return/issues"
"url": "https://github.com/codefeathers/Fuse/issues"
},
"homepage": "https://github.com/codefeathers/select-return#readme",
"homepage": "https://github.com/codefeathers/Fuse#readme",
"devDependencies": {
"eslint": "^4.19.1",
"jasmine": "^3.1.0",

87
spec/Fuse-spec.js

@ -0,0 +1,87 @@
'use strict';
const Fuse = require('../index');
/* global describe it expect */
describe("Fuse", () => {
it("Should return 'Is 10'", () => {
const a = 10;
const result = new Fuse(a)
.on(x => x > 10, () => 'Greater than 10')
.on(x => x < 10, () => 'Lesser than 10')
.on(x => x === 10, () => 'Is 10');
expect(result.resolve()).toBe('Is 10');
});
it("Should return 'Less than 10'", () => {
const a = 1;
const result = new Fuse(a)
.on(x => x > 10, () => 'Greater than 10')
.on(x => x < 10, () => 'Lesser than 10')
.on(x => x === 10, () => `Is 10`);
expect(result.resolve()).toBe('Lesser than 10');
});
it("Should return 'Greater than 10'", () => {
const a = 100;
const result = new Fuse(a)
.on(x => x > 10, () => 'Greater than 10')
.on(x => x < 10, () => 'Lesser than 10')
.on(x => x === 10, () => `Is 10`);
expect(result.resolve()).toBe('Greater than 10');
});
it(`Should return '"a" was an array'`, () => {
const a = [ 1, 2 ];
const result = new Fuse(a)
.on(x => Array.isArray(x), () => `"a" was an array`);
expect(result.resolve()).toBe(`"a" was an array`);
});
it(`Should return 'null'`, () => {
const a = 1;
const result = new Fuse(a)
.on(Array.isArray, () => `"a" was an array`);
expect(result.resolve()).toBe(null);
});
it(`Should return 'null'`, () => {
const a = 'UnexpectedString';
const result = new Fuse(a)
.on(x => x > 10, () => 'Greater than 10')
.on(x => x < 10, () => 'Lesser than 10')
.on(x => x === 10, () => `Is 10`);
expect(result.resolve()).toBe(null);
});
it(`Should return true`, () => {
const a = 'ExpectedString';
const result = new Fuse(a)
.is('ExpectedString', () => true);
expect(result.resolve()).toBe(true);
});
it(`Should return true`, () => {
const a = 'ExpectedString';
const result = new Fuse(a)
.not('UnexpectedString', () => true);
expect(result.resolve()).toBe(true);
});
});

44
spec/FuseIterable-spec.js

@ -0,0 +1,44 @@
'use strict';
const { FuseIterable } = require('../index');
/* global describe it expect */
describe("FuseIterable", () => {
it("Should return array " +
"[ 'Is 10', 'Greater than 10', 'Lesser than 10', null ]",
() => {
const a = [ 10, 20, 0, 'UnexpectedString' ];
const result = new FuseIterable(a)
.on(x => x > 10, () => 'Greater than 10')
.on(x => x < 10, () => 'Lesser than 10')
.on(x => x === 10, () => `Is 10`);
expect(result.resolve()).toEqual([
'Is 10',
'Greater than 10',
'Lesser than 10',
null
]);
});
it("Should return array " +
"[ 'Is 10', 'Greater than 10', 'Lesser than 10', null ]",
() => {
const a = [ 10, 20, 0, 'UnexpectedString' ];
const result = new FuseIterable(a)
.onField(
[ x => x > 10, () => 'Greater than 10' ],
[ x => x < 10, () => 'Lesser than 10' ],
[ x => x === 10, () => `Is 10` ]);
expect(result.resolve()).toEqual([
'Is 10',
'Greater than 10',
'Lesser than 10',
null
]);
});
});

24
spec/SelectArraySpec.js

@ -1,24 +0,0 @@
'use strict';
const Select = require('../Select');
/* global describe it expect */
describe("Select", () => {
it("Should return array" +
"[ 'Is 10', 'Greater than 10', 'Lesser than 10', null ]",
() => {
const a = [ 10, 20, 0, 'UnexpectedString' ];
const result = new Select(a)
.for(x => x > 10, () => 'Greater than 10')
.for(x => x < 10, () => 'Lesser than 10')
.for(x => x === 10, () => `Is 10`);
expect(result.resolve())
.toEqual([ 'Is 10',
'Greater than 10',
'Lesser than 10',
null ]);
});
});

51
spec/SelectSpec.js

@ -1,51 +0,0 @@
'use strict';
const Select = require('../Select');
/* global describe it expect */
describe("Select", () => {
it("Should return 'Is 10'", () => {
const a = 10;
const result = new Select(a)
.for(x => x > 10, () => 'Greater than 10')
.for(x => x < 10, () => 'Lesser than 10')
.for(x => x === 10, () => 'Is 10');
expect(result.resolve()).toBe('Is 10');
});
it("Should return 'Less than 10'", () => {
const a = 1;
const result = new Select(a)
.for(x => x > 10, () => 'Greater than 10')
.for(x => x < 10, () => 'Lesser than 10')
.for(x => x === 10, () => `Is 10`);
expect(result.resolve()).toBe('Lesser than 10');
});
it("Should return 'Greater than 10'", () => {
const a = 100;
const result = new Select(a)
.for(x => x > 10, () => 'Greater than 10')
.for(x => x < 10, () => 'Lesser than 10')
.for(x => x === 10, () => `Is 10`);
expect(result.resolve()).toBe('Greater than 10');
});
it("Should return 'null'", () => {
const a = 'UnexpectedString';
const result = new Select(a)
.for(x => x > 10, () => 'Greater than 10')
.for(x => x < 10, () => 'Lesser than 10')
.for(x => x === 10, () => `Is 10`);
expect(result.resolve()).toBe(null);
});
});
Loading…
Cancel
Save