UNPKG

mezzanine

Version:

Fantasy land union types with pattern matching

363 lines (268 loc) 11.7 kB
'use strict';Object.defineProperty(exports, "__esModule", { value: true }); var _ramda = require('ramda'); var _type = require('../type'); var _ortho = require('../ortho');var _ortho2 = _interopRequireDefault(_ortho); var _decorators = require('../decorators'); var _config = require('../config'); var _fixtures = require('../type/fixtures'); var _props = require('../utils/props'); require('../type/type-container'); var _fp = require('../utils/fp'); var _list = require('../utils/list'); var _virtualStack = require('../virtual-stack');function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _objectWithoutProperties(obj, keys) {var target = {};for (var i in obj) {if (keys.indexOf(i) >= 0) continue;if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;target[i] = obj[i];}return target;} /** * Union of types * * @module mezzanine/union */ /* eslint-disable */ //$FlowIssue var staticFantasy = (0, _props.addProperties)({ stackUpdate: Ctx => newStack => { //$FlowIssue var { typeName, desc, func } = Ctx; return Union([typeName])(desc, func, newStack); }, contramap: Ctx => function contramap(prependFunction) { //$FlowIssue var newStack = (0, _list.append)(prependFunction, Ctx.stack); //$FlowIssue var NewRecord = Ctx.stackUpdate(newStack); return NewRecord; } }); var instanceFantasy = (0, _props.addProperties)({ map: (ctx, Ctx) => function map(mapFunction) { return Ctx(ctx.chain(mapFunction)); }, chain: (ctx, Ctx) => function chain(chainFunction) { return chainFunction(ctx.toJSON()); } }); var instProps = (0, _props.addProperties)({ case: (ctx, Ctx) => cases => Ctx.case(cases, ctx.value) }); var subclassReference = (0, _props.addProperties)({ keys: (_, child) => child.keys, isMono: (_, child) => child.isMono, toJSON(_, child) { if (typeof child.toJSON === 'function') return child.toJSON(); return _.toJSON(); } }); function unrelevantCaseError(union, diff, data) { console.error(union); console.error(data); throw new Error(`Unrelevant case types ${diff.toString()} on type ${union.typeName}`); } function caseSelector( union, subtypesMap, uniqMark, cases, subtype) { var { _ = defaultCase } = cases,realCases = _objectWithoutProperties(cases, ['_']); var diff = (0, _ramda.difference)(Object.keys(realCases), union.keys); if (!(0, _ramda.isEmpty)(diff)) unrelevantCaseError(union, diff, subtype); if ((0, _fixtures.isMezzanine)(subtype) && subtype.ಠ_ಠ === uniqMark) { var currentCase = realCases[subtype.type]; // console.log(currentCase) if (typeof currentCase === 'function') return currentCase(subtype.toJSON(), union);else return _(subtype); } for (var _iterator = Object.keys(realCases), _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {var _ref;if (_isArray) {if (_i >= _iterator.length) break;_ref = _iterator[_i++];} else {_i = _iterator.next();if (_i.done) break;_ref = _i.value;}var variant = _ref; var childType = subtypesMap[variant]; var _currentCase = realCases[variant]; if (childType.is(subtype)) { var finalValue = childType.ಠ_ಠ === subtype.ಠ_ಠ ? subtype : childType(subtype); return _currentCase(finalValue.toJSON(), union); } } return _(subtype); } //$FlowIssue var caseFactory = (union, subtypesMap, uniqMark) => (cases, subtype) => caseSelector(union, subtypesMap, uniqMark, cases, subtype); /** * Make type union * * @param {string[]} [typeName] * @returns * * @example * Union`User`({ Account: String, Guest: {} }) */ function Union([typeName]) { return function UnionFabric( desc, funcBlob = {}, stack = []) { var canMatch = (0, _ortho2.default)(desc); var uniqMark = Symbol(typeName); var keys = Object.keys(desc); var values = (0, _ramda.values)(desc); var subtypes = (0, _ramda.zip)(keys, values); var subtypesMap = {}; for (var _iterator2 = subtypes, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {var _ref2;if (_isArray2) {if (_i2 >= _iterator2.length) break;_ref2 = _iterator2[_i2++];} else {_i2 = _iterator2.next();if (_i2.done) break;_ref2 = _i2.value;}var [_key4, arg] = _ref2; subtypesMap[_key4] = (0, _decorators.rename)(_key4)((0, _type.typeContainer)(_key4, typeName, arg, {}));} var caseWith = caseFactory(UnionClass, subtypesMap, uniqMark); function* iterator() { for (var _iterator3 = keys, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {var _ref3;if (_isArray3) {if (_i3 >= _iterator3.length) break;_ref3 = _iterator3[_i3++];} else {_i3 = _iterator3.next();if (_i3.done) break;_ref3 = _i3.value;}var _key = _ref3; yield [_key, subtypesMap[_key]];} } var needTransform = stack.length !== 0; function is(obj) { var val = obj; if (needTransform === true) { var initial = (0, _virtualStack.getInitialValue)(stack, val); if (initial.succ === false) return false; val = initial.val; } for (var _iterator4 = iterator(), _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {var _ref4;if (_isArray4) {if (_i4 >= _iterator4.length) break;_ref4 = _iterator4[_i4++];} else {_i4 = _iterator4.next();if (_i4.done) break;_ref4 = _i4.value;}var [_key2, pattern] = _ref4; if (pattern.is) { if (pattern.is(val)) return true; } else if (typeof pattern === 'function' && pattern(val)) return true; } return false; } var staticProps = (0, _props.addProperties)({ funcs: { value: funcBlob, enumerable: false }, desc: { value: desc, enumerable: false }, name: { value: typeName, enumerable: false }, case: { value: (0, _fp.curry2)(caseWith), enumerable: false }, stack: { value: stack, enumerable: false } }); var mainProps = (0, _props.addProperties)({ ಠ_ಠ: { value: uniqMark, enumerable: false }, //$FlowIssue [_config.typeMark]: { get: () => true, enumerable: false }, //$ FlowIssue [Symbol.iterator]: () => iterator, is: { value: () => is, inject: true, enumerable: true }, typeName: { value: typeName, enumerable: true }, canMatch: { value: canMatch, enumerable: true }, types: { value: keys, enumerable: true } }); var userMeth = (0, _props.addProperties)(funcBlob); //$FlowIssue function UnionClass(obj) { //$FlowIssue if (new.target !== UnionClass) return new UnionClass(obj); var arg = (0, _virtualStack.applyStack)(stack, obj); var data = arg && arg.value ? arg.value : arg; var matched = false; for (var _iterator5 = iterator(), _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) {var _ref5;if (_isArray5) {if (_i5 >= _iterator5.length) break;_ref5 = _iterator5[_i5++];} else {_i5 = _iterator5.next();if (_i5.done) break;_ref5 = _i5.value;}var [_key3, pattern] = _ref5; if (pattern.is(data)) { var fin = pattern(data); Object.assign(this, fin); if (fin.isMono) this.value = fin.value; subclassReference(this, fin); matched = true; break; } } if (matched === false) unmatchError(UnionClass, data); instProps(this, UnionClass); mainProps(this, UnionClass); instanceFantasy(this, UnionClass); userMeth(this, UnionClass); } staticProps(UnionClass, UnionClass); mainProps(UnionClass, UnionClass); staticFantasy(UnionClass, UnionClass); Object.assign(UnionClass, subtypesMap); // console.log(UnionClass) return UnionClass; }; } //$FlowIssue function unmatchError(union, data) { console.error(union); console.error(data); throw new TypeError('Unmatched pattern'); } var defaultCase = instance => { throw new Error(`Unmatched case on union ${instance.typeName}`); };exports.default = Union; // const Boy = Type`Boy`({ // name: String, // alive: Boolean // }, { // mutableKill: (ctx) => () => { ctx.alive = false } // }) // mutable function // const Fred = Boy({ name: 'Fred', alive: true }) // console.log(Fred) // Fred.mutableKill() // console.log(Fred) // const Brothers = Type`Brothers`({ // elder : Boy, // younger: Boy // }) // const Childs = Union`Childs`({ // Single: Boy, // Couple: Brothers, // }) // const rawData = { name: 'Fred' } // // Fred.equals(Boy({ name: 'Fred', alive: true })); /*?*/ // // Fred.equals(rawData) /*?*/ // //transforms // // Fred.map(({ name }) => ({ name: name+'dy' }))/*?*/ // deep patterns // const family1 = Childs({ name: 'John', alive: true }) // const family2 = Childs({ // elder : Fred, // younger: { name: 'Bob', alive: true } // }) // console.log(family2) // family2 /*?*/ // const onlyOne = family2.map((data) =>( console.log(data), data, family2)); // onlyOne // family1.type; /*?*/ // family2.type; /*?*/ // onlyOne.type; /*?*/ // [...family1].map(([key,value])=>key)/*?*/ // //pattern-switch // const actions = { // Single:(child) => child.name, // Couple:({ elder, younger }) => [elder.name, younger.name] // } // console.log(family2.case(actions)) // console.log(family1.case(actions)) //# sourceMappingURL=union.js.map