UNPKG

@quenk/preconditions

Version:
168 lines 6.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.schemaProperties = exports.exclude = exports.mergeRight = exports.merge = exports.map = exports.union = exports.intersect = exports.disjoint = exports.restrict = exports.isRecord = void 0; const record_1 = require("@quenk/noni/lib/data/record"); const record_2 = require("./result/failure/record"); const array_1 = require("./array"); const result_1 = require("./result"); const _1 = require("./"); /** * isRecord tests if the value is an js object (and not an Array). */ const isRecord = (value) => (0, record_1.isRecord)(value) ? (0, result_1.succeed)(value) : (0, result_1.fail)('isRecord', value); exports.isRecord = isRecord; /** * restrict applies a record of preconditions to an input object keeping * only those properties that have a matching precondition. * * If any of the preconditions fail, the whole object is considered a failure. */ const restrict = (tests) => (value) => { let add2Reports = (r, p, k) => p(value[k]).fold(onFailure(k, r), onSuccess(k, r)); let result = ((0, record_1.reduce)(tests, reports(), add2Reports)); return review(result, value); }; exports.restrict = restrict; /** * disjoint applies a record of preconditions to a javascript object * producing a new object with the final value of each precondition * and the values of any additional properties in the input object. * * If any of the preconditions fail, the whole object is considered a failure. */ const disjoint = (tests) => (value) => { let add2Reports = (r, v, k) => Object.hasOwnProperty.call(tests, k) ? tests[k](v).fold(onFailure(k, r), onSuccess(k, r)) : onSuccess(k, r)(v); let result = (0, record_1.reduce)(value, reports(), add2Reports); return review(result, value); }; exports.disjoint = disjoint; /** * intersect applies only the properties in a record of preconditions * that exist in the target input object. The resulting value is an * object with properties that exist in the input object that have had a * matching precondition applied. * * If any of the preconditions fail, the whole object is considered a failure. */ const intersect = (tests) => (value) => { let add2Reports = (r, v, k) => Object.hasOwnProperty.call(tests, k) ? tests[k](v).fold(onFailure(k, r), onSuccess(k, r)) : onSuccess(k, r)(null); let result = (0, record_1.reduce)(value, reports(), add2Reports); return review(result, value); }; exports.intersect = intersect; /** * union applies a record of preconditions to an input object. * * Union results in an object that has both the results of applied preconditions for * found properties and any additional properties on the input object. * * If any of the preconditions fail, the whole object is considered a failure. */ const union = (tests) => (value) => { let ks = (0, record_1.keys)(tests).concat((0, record_1.keys)(value)); let add2Reports = (r, k) => Object.hasOwnProperty.call(tests, k) ? tests[k](value[k]).fold(onFailure(k, r), onSuccess(k, r)) : onSuccess(k, r)(value[k]); let results = ks.reduce(add2Reports, reports()); return review(results, value); }; exports.union = union; /** * map applies the same Precondition to each property of an object. * * If any of the preconditions fail, the whole object is considered a failure. */ const map = (prec) => (0, _1.and)((0, _1.typeOf)('object'), (value) => { let fcount = 0; let failures = {}; let success = {}; for (let [key, val] of Object.entries(value)) { let result = prec(val); if (result.isLeft()) { fcount++; failures[key] = result.takeLeft(); } else { success[key] = result.takeRight(); } } return fcount > 0 ? (0, record_2.fail)(failures, value, { value }) : (0, result_1.succeed)(success); }); exports.map = map; const reports = () => ({ failures: {}, values: {} }); const review = (reports, value) => !(0, record_1.empty)(reports.failures) ? (0, record_2.fail)(reports.failures, value, { value }) : (0, result_1.succeed)(reports.values); const onFailure = (key, { failures, values }) => (f) => ({ values, failures: (0, record_1.merge)(failures, { [key]: f }) }); const onSuccess = (key, { failures, values }) => (v) => v == null ? { failures, values } : { failures, values: (0, record_1.merge)(values, { [key]: v }) }; /** * merge the properties of the value into the provided object. * * Any conflicting properties resolve to the value's property. */ const merge = (target) => (value) => { console.error('TARGET', target); console.error('VALUE ', value); return (0, result_1.succeed)((0, record_1.merge)(target, value)); }; exports.merge = merge; /** * mergeRight is like merge except conflicts are resolved with the target's * property. */ const mergeRight = (target) => (value) => (0, result_1.succeed)((0, record_1.merge)(value, target)); exports.mergeRight = mergeRight; /** * exclude the specified keys from a record value. */ const exclude = (keys) => (value) => (0, result_1.succeed)((0, record_1.exclude)(value, keys)); exports.exclude = exclude; /** * schemaProperties is a special precondition used internally for precondition * generation from object type schema. * * @param props - The preconditions parsed from the property section of * the object schema. If there are no properties, the * precondition generated will drop any property values * unless the "additionalProperties" section is specified. * * @param propsPrec - A precondition to wrap the props record in. This * should be one of "restrict", "intersect", "union" etc. * * @param addPropsPrec - A precondition parsed from the "additionalProperties" * section. This is used to intercept any not explicitly * declared properties. Properties declared in the * properties section are not passed to this precondition. */ const schemaProperties = (propsWrap, props, addPropsPrec) => { let finalPropPrec = (0, record_1.empty)(props) ? _1.identity : propsWrap(props); if (!addPropsPrec) return finalPropPrec; return (0, _1.and)((0, _1.tee)([ finalPropPrec, (0, _1.and)((0, exports.exclude)((0, record_1.keys)(props)), (0, exports.map)(addPropsPrec)) ]), (0, array_1.reduce)(() => ({}), exports.merge)); }; exports.schemaProperties = schemaProperties; //# sourceMappingURL=record.js.map