UNPKG

@quenk/preconditions

Version:
133 lines 4.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.reduce = exports.tuple = exports.map = exports.filter = exports.range = exports.minItems = exports.maxItems = exports.nonEmpty = exports.toArray = exports.isArray = void 0; const lazy = require("@quenk/noni/lib/data/lazy"); const type_1 = require("@quenk/noni/lib/data/type"); const either_1 = require("@quenk/noni/lib/data/either"); const array_1 = require("./result/failure/array"); const result_1 = require("./result"); /** * isArray tests if the value is an array */ const isArray = (a) => Array.isArray(a) ? (0, result_1.succeed)(a) : (0, result_1.fail)('isArray', a); exports.isArray = isArray; /** * toArray converts a value into an array. * * If the value is an empty string or nullish, an empty array is produced. */ const toArray = (value) => { if (Array.isArray(value)) return (0, result_1.succeed)(value); if (((0, type_1.isString)(value) && value === '') || (0, type_1.isNull)(value)) return (0, result_1.succeed)([]); else return (0, result_1.succeed)([value]); }; exports.toArray = toArray; /** * notEmpty tests if an array has at least one member. */ const nonEmpty = (value) => value.length === 0 ? (0, result_1.fail)('nonEmpty', value, { value }) : (0, result_1.succeed)(value); exports.nonEmpty = nonEmpty; /** * maxItems sets a maximum number of elements the array can contain. */ const maxItems = (target) => (value) => value.length > target ? (0, result_1.fail)('maxItems', value, { target, value }) : (0, result_1.succeed)(value); exports.maxItems = maxItems; /** * minItems sets a minimum number of elements the array can contain. */ const minItems = (target) => (value) => value.length < target ? (0, result_1.fail)('minItems', value, { target, value }) : (0, result_1.succeed)(value); exports.minItems = minItems; /** * range tests whether an array's length falls within a specific min and max range. */ const range = (min, max) => (value) => value.length < min ? (0, result_1.fail)('range.min', value, { min, max, value }) : value.length > max ? (0, result_1.fail)('range.max', value) : (0, result_1.succeed)(value); exports.range = range; /** * filter applies a precondition to each member of an array producing * an array where only the successful members are kept. */ const filter = (p) => (value) => (0, result_1.succeed)(value .map(p) .filter(e => e instanceof either_1.Right) .map(e => e.takeRight())); exports.filter = filter; /** * map applies a precondition to each member of an array. * * If the precondition fails for any of the members, * the entire array is considered a failure. */ const map = (p) => (value) => { let failed = 0; let failures = {}; let values = []; for (let i = 0; i < value.length; i++) { let result = p(value[i]); if (result.isLeft()) { failed++; failures[i] = result.takeLeft(); } else { values[i] = result.takeRight(); } } return failed === 0 ? (0, result_1.succeed)(values) : (0, either_1.left)(array_1.ArrayFailure.create(failures, value, { value })); }; exports.map = map; /** * tuple tests whether the value supplied qualifies as a tuple. * * Each precondition in the list represents a precondition for its * corresponding tuple element. */ const tuple = (list) => (value) => { if (value.length !== list.length) return (0, result_1.fail)('tuple', value); let results = value.map((v, idx) => list[idx](v)); let fails = results.filter(v => v.isLeft()).map(e => e.takeLeft()); if (fails.length > 0) { let failMap = fails.reduce((p, c, k) => { p[k] = c; return p; }, {}); return (0, either_1.left)(array_1.ArrayFailure.create(failMap, value, { value })); } return (0, result_1.succeed)(results.map(e => e.takeRight())); }; exports.tuple = tuple; /** * reduce a list of values into an accumalated value initially specified by the * parameter "accum". * * Be careful not to mutate the accumulated value directly to avoid subtle bugs. * Instead copy the value to be accumualted in each call to the reducer. */ const reduce = (getAccum, func) => (value) => { let accum = lazy.evaluate(getAccum); for (let i = 0; i < value.length; i++) { let eresult = func(accum)(value[i]); if (eresult.isLeft()) { let err = eresult.takeLeft(); return (0, either_1.left)(array_1.ArrayFailure.create({ [i]: err }, value, {})); } accum = eresult.takeRight(); } return (0, result_1.succeed)(accum); }; exports.reduce = reduce; //# sourceMappingURL=array.js.map