|
@ -1,12 +1,11 @@ |
|
|
'use strict'; |
|
|
'use strict'; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Return a function based on a condition. |
|
|
* Return a function based on a condition. |
|
|
* Functional alternative to switch-case. |
|
|
* Functional alternative to switch-case. |
|
|
* @projectname Select-Return |
|
|
* @projectname Select-Return |
|
|
* @version 1.0.0 |
|
|
* @version 1.0.0 |
|
|
* @author Muthu Kumar (@MKRhere) |
|
|
* @author Muthu Kumar (MKRhere) |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Creates a SelectValue instance with a value and optional resolve function. |
|
|
* Creates a SelectValue instance with a value and optional resolve function. |
|
@ -23,7 +22,6 @@ class SelectValue { |
|
|
this.value = value; |
|
|
this.value = value; |
|
|
if (resolve) this.resolve = (...args) => resolve(...args, value); |
|
|
if (resolve) this.resolve = (...args) => resolve(...args, value); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Default resolve prototype. Returns null when called. |
|
|
* Default resolve prototype. Returns null when called. |
|
|
* Used in case a resolve is never set. |
|
|
* Used in case a resolve is never set. |
|
@ -36,61 +34,94 @@ class SelectValue { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Creates a SelectIterable instance from an array. |
|
|
* Creates a SelectIterable instance from an array. |
|
|
* Created internally from Select.prototype.for, and not exported. |
|
|
* 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 |
|
|
|
|
|
*/ |
|
|
class SelectIterable { |
|
|
class SelectIterable { |
|
|
/** |
|
|
constructor(values, conditionals) { |
|
|
* @param {array} values - array created from Select.prototype.for |
|
|
this.values = values.map(value => value instanceof SelectValue ? value : new SelectValue(value)); |
|
|
* @param {Array<function>} tests - array of { test, consequent } objects |
|
|
this.conditionals = conditionals; |
|
|
* @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 |
|
|
* Accepts a test and consequent function each and returns a new |
|
|
* SelectIterable instance. |
|
|
* SelectIterable instance. |
|
|
* @param {Test} test - test callback function |
|
|
* SelectIterable.prototype.for works a little differently than |
|
|
* @param {function} consequent - consequent callback function |
|
|
* Select.prototype.for, by accumulating the tests and resolving all the |
|
|
* @returns {SelectIterable} - an instance of SelectIterable |
|
|
* values when .resolve() is called. |
|
|
* @memberof SelectIterable |
|
|
* @param {callback} predicate A test callback function. |
|
|
*/ |
|
|
* @callback predicate |
|
|
for(test, consequent) { |
|
|
* @param {any} value The Selected value. |
|
|
/* SelectIterable.prototype.for works a little |
|
|
* @returns {boolean} The Boolean result of the test. |
|
|
differently than Select.prototype.for, |
|
|
* @param {callback} consequent consequent callback function |
|
|
by accumulating the tests and resolving |
|
|
* @callback consequent |
|
|
all the values when .resolve() is called */ |
|
|
* @param {Array} args An arbitrary Array of arguments. |
|
|
|
|
|
* @param {any} value The Selected value. |
|
|
|
|
|
* @returns {any} |
|
|
|
|
|
* @returns {SelectIterable} an instance of SelectIterable |
|
|
|
|
|
* @memberof SelectIterable |
|
|
|
|
|
*/ |
|
|
|
|
|
if(predicate, consequent) { |
|
|
|
|
|
return new SelectIterable(this.values, [ |
|
|
|
|
|
...this.conditionals, |
|
|
|
|
|
{predicate, consequent} |
|
|
|
|
|
]); |
|
|
|
|
|
} |
|
|
|
|
|
forField(...pairs) { |
|
|
|
|
|
var pair; |
|
|
|
|
|
var callback; |
|
|
|
|
|
var even; |
|
|
|
|
|
pairs.forEach((pair, index) => { |
|
|
|
|
|
even = index % 2 === 0; |
|
|
|
|
|
pair = this.conditionals[this.conditionals.length]; |
|
|
|
|
|
if (pair.length === 2) { |
|
|
|
|
|
this.conditionals.push({}); |
|
|
|
|
|
}; |
|
|
|
|
|
callback = conditionals[loc]; |
|
|
|
|
|
if (typeof callback === "object") { |
|
|
|
|
|
if (Array.isArray(callback)) { |
|
|
|
|
|
pair.predicate = callback[0]; |
|
|
|
|
|
pair.consequent = callback[0]; |
|
|
|
|
|
} else { |
|
|
|
|
|
Object.assign(pair, { |
|
|
|
|
|
predicate: callback.predicate, |
|
|
|
|
|
consequent: callback.consequent |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
if (even) pair.predicate = callback; |
|
|
|
|
|
if (!even) pair.consequent = callback; |
|
|
|
|
|
}, this); |
|
|
return new SelectIterable( |
|
|
return new SelectIterable( |
|
|
this.values, |
|
|
this.values, |
|
|
[ ...this.tests, { test, consequent } ] |
|
|
[...this.conditionals, ...conditionals] |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
subset(value, consequent) { |
|
|
resolve(...args) { |
|
|
return this.if(this.value.every(element => element in value)) |
|
|
/* When .resolve() is called, a resolved value |
|
|
} |
|
|
is generated for each value in the array */ |
|
|
superset(value, consequent) { |
|
|
return this.values.map(item => { |
|
|
return this.if(value.every(element => element in this.value)); |
|
|
const resolver = this |
|
|
|
|
|
.tests |
|
|
|
|
|
.find(x => x.test(item.value) |
|
|
|
|
|
? x.consequent |
|
|
|
|
|
: null); |
|
|
|
|
|
return resolver |
|
|
|
|
|
? resolver.consequent(...args, item.value) |
|
|
|
|
|
: null; |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
SelectIterable.prototype.resolve = function (...args) { |
|
|
|
|
|
return this.values.map(item => { |
|
|
|
|
|
const resolver = this.conditionals.find(conditional => |
|
|
|
|
|
conditional.predicate(item.value) |
|
|
|
|
|
? conditional.consequent |
|
|
|
|
|
: null |
|
|
|
|
|
); |
|
|
|
|
|
return resolver |
|
|
|
|
|
? resolver.consequent(...args, this.value) |
|
|
|
|
|
: null; |
|
|
|
|
|
}, this); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Creates a new Select instance. |
|
|
* Creates a new Select instance. |
|
@ -107,33 +138,46 @@ class Select extends SelectValue { |
|
|
super(value, resolve); |
|
|
super(value, resolve); |
|
|
this.iterable = typeof value === "object" && Symbol.iterator in value; |
|
|
this.iterable = typeof value === "object" && Symbol.iterator in value; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Accepts a test and consequent function each and returns a new |
|
|
* Accepts a test and consequent function each and returns a new |
|
|
* Select or SelectIterable instance. |
|
|
* Select or SelectIterable instance. |
|
|
* @param {function} test - test callback function |
|
|
* @param {callback} predicate A test callback function. |
|
|
* @param {function} consequent - consequent callback function |
|
|
* @callback predicate |
|
|
* @returns {Select|SelectIterable} - Returns a SelectIterable instance |
|
|
* @param {any} value The Selected value. |
|
|
* if value was array, or a Select instance otherwise |
|
|
* @returns {boolean} The Boolean result of the test. |
|
|
* @memberof Select |
|
|
* @param {callback} consequent consequent callback function |
|
|
*/ |
|
|
* @callback consequent |
|
|
for(test, consequent) { |
|
|
* @param {Array} args An arbitrary Array of arguments. |
|
|
|
|
|
* @param {any} value The Selected value. |
|
|
|
|
|
* @returns {any} |
|
|
|
|
|
* @returns {(Select|SelectIterable)} - Returns a SelectIterable instance |
|
|
|
|
|
* if value was array, or a Select instance otherwise |
|
|
|
|
|
* @memberof Select |
|
|
|
|
|
*/ |
|
|
|
|
|
if(predicate, consequent) { |
|
|
if (this.iterable) { |
|
|
if (this.iterable) { |
|
|
/* If the value passed to the constructor is |
|
|
/* If the value passed to the constructor is an |
|
|
an array, initialise a new SelectIterable |
|
|
iterable, return a new SelectIterable using the |
|
|
with the array and { test, consequent } pair |
|
|
iterable and { test, consequent } pair.*/ |
|
|
and return */ |
|
|
|
|
|
return new SelectIterable( |
|
|
return new SelectIterable( |
|
|
Array.from(this.value), |
|
|
Array.from(this.value), |
|
|
[ { test, consequent } ], |
|
|
[{ predicate, consequent }] |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
if (test(this.value)) return new Select(this.value, consequent); |
|
|
if (predicate(this.value)) { |
|
|
|
|
|
return new Select(this.value, consequent); |
|
|
|
|
|
} |
|
|
/* If the test doesn't pass, just pass the Select |
|
|
/* If the test doesn't pass, just pass the Select |
|
|
instance along the chain until a test passes, |
|
|
instance along the chain until a test passes, |
|
|
or .resolve() is called */ |
|
|
or .resolve() is called */ |
|
|
return this; |
|
|
return this; |
|
|
} |
|
|
} |
|
|
|
|
|
is(value, consequent) { |
|
|
|
|
|
return this.if(value === this.value, consequent); |
|
|
|
|
|
} |
|
|
|
|
|
isNot(value, consequent) { |
|
|
|
|
|
return this.if(value !== this.value, consequent) |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
module.exports = Select; |
|
|
module.exports = Select; |
|
|