UNPKG

@typed/fp

Version:

Data Structures and Resources for fp-ts

609 lines 19.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ap = exports.Chain = exports.chain = exports.fromIO = exports.tupled = exports.flap = exports.bindTo = exports.Functor = exports.Pointed = exports.strict = exports.condemmMissingKeys = exports.condemnUnexpectedKeys = exports.absolve = exports.absolveWhen = exports.condemn = exports.condemnWhen = exports.map = exports.of = exports.URI = exports.lazy = exports.intersect = exports.tuple = exports.unexpectedIndexes = exports.missingIndexes = exports.fromTuple = exports.record = exports.fromRecord = exports.struct = exports.unexpectedKeys = exports.missingKeys = exports.fromStruct = exports.array = exports.fromArray = exports.unknownRecord = exports.unknownArray = exports.optional = exports.nullable = exports.literal = exports.sum = exports.date = exports.isDate = exports.union = exports.refine = exports.WithRefine = exports.dateFromISOString = exports.boolean = exports.number = exports.string = exports.compose = exports.fromRefinement = void 0; exports.assertStrict = exports.assert = exports.jsonParse = exports.jsonParseFromString = exports.WithUnion = exports.Schemable = exports.Monad = exports.Do = exports.getApplicativeMonoid = exports.Applicative = exports.getApplySemigroup = exports.apT = exports.apSecond = exports.apS = exports.apFirst = exports.Apply = exports.bind = exports.chainFirst = void 0; const tslib_1 = require("tslib"); /** * Decoder is a data structure for representing runtime representations of your types. * @since 0.9.4 */ const date_fns_1 = require("date-fns"); const App = (0, tslib_1.__importStar)(require("fp-ts/Applicative")); const Ap = (0, tslib_1.__importStar)(require("fp-ts/Apply")); const Ch = (0, tslib_1.__importStar)(require("fp-ts/Chain")); const Ei = (0, tslib_1.__importStar)(require("fp-ts/Either")); const F = (0, tslib_1.__importStar)(require("fp-ts/Functor")); const N = (0, tslib_1.__importStar)(require("fp-ts/number")); const Predicate_1 = require("fp-ts/Predicate"); const RA = (0, tslib_1.__importStar)(require("fp-ts/ReadonlyArray")); const ReadonlyNonEmptyArray_1 = require("fp-ts/ReadonlyNonEmptyArray"); const S = (0, tslib_1.__importStar)(require("fp-ts/string")); const DE = (0, tslib_1.__importStar)(require("./DecodeError")); const DecodeError_1 = require("./DecodeError"); const function_1 = require("./function"); const internal_1 = require("./internal"); const St = (0, tslib_1.__importStar)(require("./struct")); const struct_1 = require("./struct"); const T = (0, tslib_1.__importStar)(require("./These")); /** * @category Constructor * @since 0.9.4 */ function fromRefinement(refinement, expected) { return { decode: (i) => (refinement(i) ? T.right(i) : T.left([DE.leaf(i, expected)])), }; } exports.fromRefinement = fromRefinement; /** * @category Combinator * @since 0.9.4 */ const compose = (second) => (first) => { const { chain } = T.getChain(DE.getSemigroup()); return { decode: (i) => (0, function_1.pipe)(i, first.decode, chain(second.decode)), }; }; exports.compose = compose; /** * @category Constructor * @since 0.9.4 */ exports.string = fromRefinement((x) => typeof x === 'string', 'string'); /** * @category Constructor * @since 0.9.4 */ exports.number = fromRefinement((x) => typeof x === 'number', 'number'); /** * @category Constructor * @since 0.9.4 */ exports.boolean = fromRefinement((x) => typeof x === 'boolean', 'boolean'); /** * @category Decoder * @since 0.9.5 */ exports.dateFromISOString = { decode: (i) => { const date = (0, date_fns_1.parseISO)(i); const time = date.getTime(); if (Number.isNaN(time)) { return T.left([(0, DecodeError_1.leaf)(i, `dateFromISOString`)]); } return T.right(date); }, }; /** * @category Instance * @since 0.9.5 */ exports.WithRefine = { refine: (refinment, id) => (from) => (0, function_1.pipe)(from, (0, exports.compose)(fromRefinement(refinment, id))), }; /** * @category Combinator * @since 0.9.5 */ exports.refine = exports.WithRefine.refine; /** * @category Constructor * @since 0.9.4 */ const union = (second) => (first) => { const { concat } = DE.getSemigroup(); return { decode: (i) => (0, function_1.pipe)(i, first.decode, T.mapLeft((errors) => [DE.member(0, errors)]), T.matchW((e1) => (0, function_1.pipe)(i, second.decode, T.mapLeft((errors) => [DE.member(1, errors)]), T.matchW((e2) => (0, function_1.pipe)(e1, concat(e2), T.left), T.right, (e2, a) => T.both((0, function_1.pipe)(e1, concat(e2)), a))), T.right, (e1, o1) => (0, function_1.pipe)(i, second.decode, T.mapLeft((errors) => [DE.member(1, errors)]), T.matchW((e2) => T.both((0, function_1.pipe)(e1, concat(e2)), o1), T.right, (e2) => T.both((0, function_1.pipe)(e1, concat(e2)), o1))))), }; }; exports.union = union; /** * @category Refinement * @since 0.9.6 */ const isDate = (x) => x instanceof Date; exports.isDate = isDate; /** * @category Constructor * @since 0.9.6 */ exports.date = (0, function_1.pipe)(exports.string, (0, exports.refine)(exports.isDate, 'Date'), (0, exports.union)(fromRefinement(exports.isDate, 'Date'))); /** * @category Constructor * @since 0.9.6 */ const sum = (tag) => (members) => { return { decode: (i) => (0, function_1.pipe)(i, struct(St.make(tag, (0, exports.literal)(...Object.keys(members)))).decode, T.matchW(T.left, (a) => members[a[tag]].decode(a), ([first, ...rest], a) => (0, function_1.pipe)(members[a[tag]].decode(a), T.mapLeft((e) => [first, ...rest, ...e])))), }; }; exports.sum = sum; /** * @category Constructor * @since 0.9.6 */ const literal = (...literals) => fromRefinement((x) => literals.includes(x), literals.join(' | ')); exports.literal = literal; /** * @category Combinator * @since 0.9.4 */ exports.nullable = (0, exports.union)(fromRefinement((x) => x === null, 'null')); /** * @category Combinator * @since 0.9.4 */ exports.optional = (0, exports.union)(fromRefinement((x) => x === undefined, 'undefined')); /** * @category Constructor * @since 0.9.4 */ exports.unknownArray = fromRefinement(Array.isArray, 'Array<unknown>'); /** * @category Constructor * @since 0.9.4 */ exports.unknownRecord = fromRefinement((x) => !!x && !Array.isArray(x) && typeof x === 'object', 'Record<string, unknown>'); /** * @category Constructor * @since 0.9.4 */ const fromArray = (member) => { const { concat } = T.getSemigroup(DE.getSemigroup(), RA.getSemigroup()); return { decode: (inputs) => { const array = inputs.map((input, index) => (0, function_1.pipe)(input, member.decode, T.mapLeft((e) => [DE.index(index, e)]), T.map((o) => [o]))); return array.reduce((acc, x) => (0, function_1.pipe)(x, concat(acc)), T.right([])); }, }; }; exports.fromArray = fromArray; /** * @category Constructor * @since 0.9.4 */ const array = (member) => (0, function_1.pipe)(exports.unknownArray, (0, exports.compose)((0, exports.fromArray)(member))); exports.array = array; /** * @category Constructor * @since 0.9.4 */ const fromStruct = (properties) => { const { concat } = T.getSemigroup(DE.getSemigroup(), St.getAssignSemigroup()); return { decode: (i) => { const expectedKeys = Object.keys(properties); const remainingKeys = expectedKeys.filter((k) => k in i); const struct = remainingKeys.map((k) => (0, function_1.pipe)(properties[k].decode(i[k]), T.mapLeft((e) => [DE.key(k, e)]), T.map((o) => (0, struct_1.make)(k, o)))); const result = struct.reduce((acc, x) => (0, function_1.pipe)(x, concat(acc)), T.right({})); return result; }, }; }; exports.fromStruct = fromStruct; /** * @category Constructor * @since 0.9.4 */ function missingKeys(properties) { const diff = RA.difference(S.Eq); return { decode: (i) => { const expectedKeys = Object.keys(properties); const actualKeys = Object.keys(i); const missingKeys = (0, function_1.pipe)(expectedKeys, diff(actualKeys)); const result = RA.isNonEmpty(missingKeys) ? T.both([DE.missingKeys([missingKeys[0], ...missingKeys.slice(1)])], i) : T.right(i); return result; }, }; } exports.missingKeys = missingKeys; /** * @category Constructor * @since 0.9.4 */ function unexpectedKeys(properties) { const diff = RA.difference(S.Eq); return { decode: (i) => { const expectedKeys = Object.keys(properties); const actualKeys = Object.keys(i); const unexpectedKeys = (0, function_1.pipe)(actualKeys, diff(expectedKeys)); const result = RA.isNonEmpty(unexpectedKeys) ? T.both([DE.unexpectedKeys([unexpectedKeys[0], ...unexpectedKeys.slice(1)])], i) : T.right(i); return result; }, }; } exports.unexpectedKeys = unexpectedKeys; /** * @category Constructor * @since 0.9.4 */ function struct(properties) { return (0, function_1.pipe)(exports.unknownRecord, (0, exports.compose)(missingKeys(properties)), (0, exports.compose)(unexpectedKeys(properties)), (0, exports.compose)((0, exports.fromStruct)(properties))); } exports.struct = struct; /** * @category Constructor * @since 0.9.4 */ function fromRecord(decoder) { const { concat } = T.getSemigroup(DE.getSemigroup(), St.getAssignSemigroup()); return { decode: (i) => { const results = Object.entries(i).map(([key, value]) => (0, function_1.pipe)(value, decoder.decode, T.mapLeft((errors) => [DE.key(key, errors)]), T.map((b) => ({ [key]: b })))); return results.reduce((acc, x) => (0, function_1.pipe)(x, concat(acc)), T.of(Object.create(null))); }, }; } exports.fromRecord = fromRecord; /** * @category Constructor * @since 0.9.6 */ const record = (codomain) => (0, function_1.pipe)(exports.unknownRecord, (0, exports.compose)(fromRecord(codomain))); exports.record = record; /** * @category Constructor * @since 0.9.4 */ function fromTuple(...components) { const { concat } = T.getSemigroup(DE.getSemigroup(), RA.getSemigroup()); return { decode: (input) => { const tuple = components.map((d, i) => (0, function_1.pipe)(d.decode(input[i]), T.mapLeft((errors) => [DE.index(i, errors)]), T.map((o) => [o]))); const result = tuple.reduce((acc, x) => (0, function_1.pipe)(x, concat(acc)), T.right([])); return result; }, }; } exports.fromTuple = fromTuple; /** * @category Constructor * @since 0.9.4 */ function missingIndexes(...components) { const diff = RA.difference(N.Eq); return { decode: (i) => { const expectedKeys = Object.keys(components).map(parseFloat); const actualKeys = Object.keys(i).map(parseFloat); const missingKeys = (0, function_1.pipe)(expectedKeys, diff(actualKeys)); const result = RA.isNonEmpty(missingKeys) ? T.both([DE.missingIndexes([missingKeys[0], ...missingKeys.slice(1)])], i) : T.right(i); return result; }, }; } exports.missingIndexes = missingIndexes; /** * @category Constructor * @since 0.9.4 */ function unexpectedIndexes(...components) { const diff = RA.difference(S.Eq); return { decode: (i) => { const expectedKeys = Object.keys(components); const actualKeys = Object.keys(i); const unexpectedKeys = (0, function_1.pipe)(actualKeys, diff(expectedKeys)); const result = RA.isNonEmpty(unexpectedKeys) ? T.both([DE.unexpectedKeys([unexpectedKeys[0], ...unexpectedKeys.slice(1)])], i) : T.right(i); return result; }, }; } exports.unexpectedIndexes = unexpectedIndexes; /** * @category Constructor * @since 0.9.4 */ function tuple(...components) { return (0, function_1.pipe)(exports.unknownArray, (0, exports.compose)(missingIndexes(...components)), (0, exports.compose)(unexpectedIndexes(...components)), (0, exports.compose)(fromTuple(...components))); } exports.tuple = tuple; /** * @category Combinator * @since 0.9.6 */ const intersect = (second) => (first) => { const { concat } = T.getSemigroup(DE.getSemigroup(), St.getAssignSemigroup()); return { decode: (i) => concat(second.decode(i))(first.decode(i)), }; }; exports.intersect = intersect; /** * @category Constructor * @since 0.9.6 */ const lazy = (id, f) => { const get = (0, internal_1.memoize)((_) => f()); return { decode: (i) => (0, function_1.pipe)(get().decode(i), T.mapLeft((errors) => [DE.lazy(id, errors)])), }; }; exports.lazy = lazy; /** * @category URI * @since 0.9.4 */ exports.URI = '@typed/fp/Decoder'; /** * @category Constructor * @since 0.9.4 */ const of = (value) => ({ decode: () => T.right(value), }); exports.of = of; /** * @category Combinator * @since 0.9.4 */ const map = (f) => (decoder) => ({ decode: (i) => (0, function_1.pipe)(i, decoder.decode, T.map(f)), }); exports.map = map; /** * @category Combinator * @since 0.9.4 */ function condemnWhen(predicate) { return (decoder) => ({ decode: (i) => (0, function_1.pipe)(i, decoder.decode, T.matchW(T.left, T.right, (errors, a) => { const { left: absolved, right: condemned } = (0, function_1.pipe)(errors, RA.map(Ei.fromPredicate(predicate)), RA.separate); return RA.isNonEmpty(condemned) ? T.left(condemned) : RA.isNonEmpty(absolved) ? T.both(absolved, a) : T.right(a); })), }); } exports.condemnWhen = condemnWhen; /** * @category Combinator * @since 0.9.4 */ exports.condemn = condemnWhen(() => true); /** * @category Combinator * @since 0.9.4 */ function absolveWhen(predicate) { return (decoder) => ({ decode: (i) => (0, function_1.pipe)(i, decoder.decode, T.matchW(T.left, T.right, (errors, a) => { const { left: condemned, right: absolved } = (0, function_1.pipe)(errors, RA.map(Ei.fromPredicate((0, Predicate_1.not)(predicate))), RA.separate); return RA.isNonEmpty(absolved) ? T.right(a) : RA.isNonEmpty(condemned) ? T.both(condemned, a) : T.right(a); })), }); } exports.absolveWhen = absolveWhen; /** * @category Combinator * @since 0.9.4 */ exports.absolve = absolveWhen(() => true); /** * @category Combinator * @since 0.9.4 */ exports.condemnUnexpectedKeys = condemnWhen((d) => d._tag === 'UnexpectedKeys'); /** * @category Combinator * @since 0.9.4 */ exports.condemmMissingKeys = condemnWhen((d) => d._tag === 'MissingKeys'); /** * @category Combinator * @since 0.9.4 */ exports.strict = condemnWhen((d) => d._tag === 'UnexpectedKeys' || d._tag === 'MissingKeys'); /** * @category Instance * @since 0.9.4 */ exports.Pointed = { of: exports.of, }; /** * @category Instance * @since 0.9.4 */ exports.Functor = { map: exports.map, }; /** * @category Combinator * @since 0.9.4 */ exports.bindTo = F.bindTo(exports.Functor); /** * @category Combinator * @since 0.9.4 */ exports.flap = F.flap(exports.Functor); /** * @category Combinator * @since 0.9.4 */ exports.tupled = F.tupled(exports.Functor); /** * @category Constructor * @since 0.9.4 */ const fromIO = (io) => ({ decode: () => T.right(io()), }); exports.fromIO = fromIO; /** * @category Combinator * @since 0.9.4 */ const chain = (f) => (decoder) => ({ decode: (i) => (0, function_1.pipe)(i, decoder.decode, T.matchW(T.left, (a) => f(a).decode(i), (errors, a) => (0, function_1.pipe)(i, f(a).decode, T.mapLeft((0, ReadonlyNonEmptyArray_1.concatW)(errors))))), }); exports.chain = chain; /** * @category Constructor * @since 0.9.4 */ exports.Chain = { map: exports.map, chain: exports.chain, }; /** * @category Combinator * @since 0.9.4 */ exports.ap = Ch.ap(exports.Chain); /** * @category Combinator * @since 0.9.4 */ exports.chainFirst = Ch.chainFirst(exports.Chain); /** * @category Combinator * @since 0.9.4 */ exports.bind = Ch.bind(exports.Chain); /** * @category Instance * @since 0.9.4 */ exports.Apply = { map: exports.map, ap: exports.ap, }; /** * @category Combinator * @since 0.9.4 */ exports.apFirst = Ap.apFirst(exports.Apply); /** * @category Combinator * @since 0.9.4 */ exports.apS = Ap.apS(exports.Apply); /** * @category Combinator * @since 0.9.4 */ exports.apSecond = Ap.apSecond(exports.Apply); /** * @category Combinator * @since 0.9.4 */ exports.apT = Ap.apT(exports.Apply); /** * @category Typeclass Constructor * @since 0.9.4 */ exports.getApplySemigroup = Ap.getApplySemigroup(exports.Apply); /** * @category Instance * @since 0.9.4 */ exports.Applicative = { of: exports.of, ...exports.Apply, }; /** * @category Combinator * @since 0.9.4 */ exports.getApplicativeMonoid = App.getApplicativeMonoid(exports.Applicative); /** * @category Constructor * @since 0.9.4 */ exports.Do = (0, exports.fromIO)(() => Object.create(null)); /** * @category Instance * @since 0.9.4 */ exports.Monad = { ...exports.Pointed, ...exports.Chain, }; /** * @category Instance * @since 0.9.5 */ exports.Schemable = { URI: exports.URI, literal: exports.literal, string: exports.string, number: exports.number, boolean: exports.boolean, date: exports.date, nullable: exports.nullable, optional: exports.optional, struct: struct, record: exports.record, array: exports.array, tuple: tuple, intersect: exports.intersect, sum: exports.sum, lazy: exports.lazy, branded: ((d) => d), unknownArray: exports.unknownArray, unknownRecord: exports.unknownRecord, }; /** * @category Instance * @since 0.9.5 */ exports.WithUnion = { union: exports.union, }; /** * @category Decoder * @since 0.9.5 */ exports.jsonParseFromString = { decode: (i) => { try { return T.right(JSON.parse(i)); } catch (e) { return T.left([DE.leaf(i, `Json`)]); } }, }; /** * @category Decoder * @since 0.9.5 */ exports.jsonParse = (0, function_1.pipe)(exports.string, (0, exports.compose)(exports.jsonParseFromString)); /** * Throw if not a valid decoder. Absolves optional errors * @category Interpreter * @since 0.9.5 */ const assert = (decoder) => (i) => (0, function_1.pipe)(i, decoder.decode, T.absolve, Ei.matchW((errors) => { throw new Error(DE.drawErrors(errors)); }, (o) => o)); exports.assert = assert; /** * Throw if not a valid decoder. Condemns optional errors * @category Interpreter * @since 0.9.5 */ const assertStrict = (decoder) => (i) => (0, function_1.pipe)(i, decoder.decode, T.condemn, Ei.matchW((errors) => { throw new Error(DE.drawErrors(errors)); }, (o) => o)); exports.assertStrict = assertStrict; //# sourceMappingURL=Decoder.js.map