All files EnumType.js

100% Statements 24/24
88.24% Branches 15/17
100% Functions 8/8
100% Lines 19/19
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53        3x 18x 35x 4x   18x         29x       4x 4x 2x         15x   14x   14x   13x 13x   13x 9x       1x     18x           18x        
 
import { reduceTypeConstructors, reduceTypeNames, prop, error, EnumToken, isArray } from './utils';
 
// EnumType :: Array String | Object * -> EnumType
const EnumType = enumTokens => {
    const types = isArray(enumTokens)
        ? enumTokens.map(name => EnumToken({ name }))
        : Object.keys(enumTokens).map(name => EnumToken({ name, props: enumTokens[name] }));
 
    let self = {
        // types :: Array String
        types: types.map(prop(['name'])),
 
        // isValidConstructor :: String -> Boolean
        isValidConstructor: c => c === '_' || !!self[c],
 
        // matchToDefault :: Object (...a -> b) -> Array a ~> b
        matchToDefault: (patternMap, args = []) => {
            const defaultAction = patternMap._;
            if(!defaultAction) return error('Missing default case _ for match');
            return defaultAction(...args);
        },
 
        // match :: EnumTagType ~> Object (a -> b) -> b
        match: (token, patternMap) => {
            if (!token || !token.name) return error('Invalid token passed to match');
 
            const isValidPattern = !!Object.keys(patternMap).filter(self.isValidConstructor).length;
 
            if(!isValidPattern) return error('Invalid constructor in pattern');
 
            const action = patternMap[token.name];
            const args = token.args || [];
 
            if (!action) return self.matchToDefault(patternMap, args);
            return action(...args);
        },
 
        // caseOf :: Object (a -> b) ~> EnumTagType -> b
        caseOf: patternMap => token => self.match(token, patternMap),
    };
 
    self = {
        // {String} :: EnumAction
        ...reduceTypeConstructors(self, types),
        ...self,
    };
 
    return self;
};
 
export default EnumType;