Skip to content

Commit

Permalink
feat: refactor Condition code
Browse files Browse the repository at this point in the history
  • Loading branch information
vonagam committed Feb 7, 2019
1 parent 64ec24c commit 9047a4f
Showing 1 changed file with 48 additions and 33 deletions.
81 changes: 48 additions & 33 deletions src/Condition.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,67 @@
import has from 'lodash/has';
import isSchema from './util/isSchema';

function callOrConcat(schema) {
if (typeof schema === 'function') return schema;
if (!schema) return base => base;
return (base, options) => base.concat(schema.resolve(options));
function wrapCusomFn(fn) {
return function(...args) {
args.pop();
return fn.apply(this, args);
};
}

class Conditional {
constructor(refs, options) {
let { is, then, otherwise } = options;
function makeConditionPredicate(is) {
if (typeof is === 'function') return is;

return (...values) => values.every(value => value === is);
}

this.refs = [].concat(refs);
function makeBranchCustomizer(branch) {
if (!branch) return () => undefined;

if (typeof branch === 'function') return schema => branch(schema);

return (schema, options) => schema.concat(branch.resolve(options));
}

then = callOrConcat(then);
otherwise = callOrConcat(otherwise);
function makeFn(options) {
if (typeof options === 'function') return wrapCusomFn(options);

if (typeof options === 'function') this.fn = options;
else {
if (!has(options, 'is'))
throw new TypeError('`is:` is required for `when()` conditions');
if (!has(options, 'is'))
throw new TypeError('`is:` is required for `when()` conditions');

if (!options.then && !options.otherwise)
throw new TypeError(
'either `then:` or `otherwise:` is required for `when()` conditions',
);
if (!options.then && !options.otherwise)
throw new TypeError(
'either `then:` or `otherwise:` is required for `when()` conditions',
);

let isFn =
typeof is === 'function'
? is
: (...values) => values.every(value => value === is);
let { is, then, otherwise } = options;

this.fn = function(...values) {
let options = values.pop();
let schema = values.pop();
let option = isFn(...values) ? then : otherwise;
is = makeConditionPredicate(is);
then = makeBranchCustomizer(then);
otherwise = makeBranchCustomizer(otherwise);

return option(schema, options);
};
}
let fn = function(...args) {
let options = args.pop();
let schema = args.pop();
let customizer = is(...args) ? then : otherwise;

return customizer(schema, options);
};

return fn;
}

class Condition {
constructor(refs, options) {
this.refs = refs;
this.fn = makeFn(options);
}

resolve(ctx, options) {
resolve(base, options) {
let values = this.refs.map(ref => ref.getValue(options));

let schema = this.fn.apply(ctx, values.concat(ctx, options));
let schema = this.fn.apply(base, values.concat(base, options));

if (schema === undefined) return ctx;
if (schema === undefined || schema === base) return base;

if (!isSchema(schema))
throw new TypeError('conditions must return a schema object');
Expand All @@ -55,4 +70,4 @@ class Conditional {
}
}

export default Conditional;
export default Condition;

0 comments on commit 9047a4f

Please sign in to comment.