@unsplash/sum-types-io-ts
Version:
io-ts bindings for @unsplash/sum-types.
85 lines (84 loc) • 7.07 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getInternallyTaggedCodec = exports.getUntaggedCodec = exports.getAdjacentlyTaggedCodec = exports.getExternallyTaggedCodec = exports.getCodecFromNullaryTag = exports.getCodecFromPrimitiveMappedNullaryTag = exports.MappedType = exports.getCodecFromMappedNullaryTag = exports.getCodec = exports.getCodecFromSerialized = exports.getSerializedCodec = exports.nullaryFromEmpty = exports.nullaryFrom = void 0;
const Sum = require("@unsplash/sum-types");
const function_1 = require("fp-ts/function");
const t = require("io-ts");
const A = require("fp-ts/Array");
const O = require("fp-ts/Option");
const E = require("fp-ts/Either");
const Map = require("fp-ts/Map");
const R = require("fp-ts/Record");
const Str = require("fp-ts/string");
const Tuple_1 = require("fp-ts/Tuple");
const Eq_1 = require("fp-ts/Eq");
const unknownSerialize = (x) => {
return O.tryCatch(() => Sum.serialize(x));
};
const unsafeGetTags = Object.keys;
const union1 = (xs, name = "union1") => xs[1] === undefined
? new t.UnionType(name, xs[0].is, xs[0].validate, xs[0].encode, xs)
: t.union(xs, name);
const foldToUnion = (f) => (cs, name = "Sum union") => (0, function_1.pipe)(cs, Object.entries, A.map(([k, v]) => f([k, v])), ([x, ...ys]) => union1([x, ...ys], name));
const nullaryFrom = (to) => (from) => new t.Type(`nullaryFrom(${from.name})`, t.null.is, (i, c) => (0, function_1.pipe)(from.validate(i, c), E.map((0, function_1.constant)(null))), (0, function_1.constant)(to));
exports.nullaryFrom = nullaryFrom;
exports.nullaryFromEmpty = (0, exports.nullaryFrom)(undefined)(t.union([t.undefined, t.null, t.type({})]));
const getSerializedCodec = () => (cs, name = "Serialized Sum") => foldToUnion((0, function_1.flow)((0, Tuple_1.mapFst)(t.literal), xs => t.tuple(xs)))(cs, name);
exports.getSerializedCodec = getSerializedCodec;
const getCodecFromSerialized = (sum) => (cs, name = "Sum") => {
const sc = (0, exports.getSerializedCodec)()(cs, name);
return new t.Type(name, (x) => (0, function_1.pipe)(unknownSerialize(x), O.exists(sc.is)), (0, function_1.flow)(sc.validate, E.map(Sum.deserialize(sum))), (0, function_1.flow)(Sum.serialize, sc.encode));
};
exports.getCodecFromSerialized = getCodecFromSerialized;
const getCodec = (sum) => (cs, name = "Sum") => {
const sc = (0, exports.getSerializedCodec)()(cs, name);
return new t.Type(name, (x) => (0, function_1.pipe)(unknownSerialize(x), O.exists(sc.is)), (i, c) => (0, function_1.pipe)(i, unknownSerialize, O.matchW(() => t.failure(i, c), E.right), E.chain(sc.decode), E.map(Sum.deserialize(sum))), (0, function_1.flow)(Sum.serialize, sc.encode, Sum.deserialize(sum)));
};
exports.getCodec = getCodec;
const getCodecFromMappedNullaryTag = (sum) => (from, to) => (tags, name = "Sum Mapped Tag") => {
const isKnownTag = (x) => tags.includes(x);
return new t.Type(name, (x) => (0, function_1.pipe)(unknownSerialize(x), O.exists(y => isKnownTag(y[0]) && y[1] === null)), (x, ctx) => (0, function_1.pipe)(x, from, O.match(() => t.failure(x, ctx), k => t.success(Sum.deserialize(sum)([k, null])))), (0, function_1.flow)(Sum.serialize, x => x[0], to));
};
exports.getCodecFromMappedNullaryTag = getCodecFromMappedNullaryTag;
class MappedType extends t.Type {
Map;
_tag = "@unsplash/sum-types-io-ts/MappedType";
constructor(name, is, validate, encode, Map) {
super(name, is, validate, encode);
this.Map = Map;
}
}
exports.MappedType = MappedType;
const getCodecFromPrimitiveMappedNullaryTag = (sum) => (tos, name = "Sum Primitive Mapped Tag") => {
const froms = (0, function_1.pipe)(tos, R.reduceWithIndex(Str.Ord)(new globalThis.Map(), (k, xs, v) => Map.upsertAt(Eq_1.eqStrict)(v, k)(xs)));
const codec = (0, exports.getCodecFromMappedNullaryTag)(sum)(x => Map.lookup(Eq_1.eqStrict)(x)(froms), x => tos[x])(unsafeGetTags(tos), name);
return new MappedType(codec.name, codec.is, codec.validate, codec.encode, tos);
};
exports.getCodecFromPrimitiveMappedNullaryTag = getCodecFromPrimitiveMappedNullaryTag;
const getCodecFromNullaryTag = (sum) => (tags, name = "Sum Tag") => (0, exports.getCodecFromPrimitiveMappedNullaryTag)(sum)((0, function_1.pipe)(tags, A.reduce({}, (xs, y) => R.upsertAt(y, y)(xs))), name);
exports.getCodecFromNullaryTag = getCodecFromNullaryTag;
const getExternallyTaggedMemberCodec = (sum) => (k) => (vc, name = "Sum") => new t.Type(name, (x) => (0, function_1.pipe)(unknownSerialize(x), O.exists(y => y[0] === k && vc.is(y[1]))), (i, ctx) => (0, function_1.pipe)(typeof i === "object" && i !== null && k in i
? E.right(i)
: t.failure(i, ctx, `Missing key "${k}"`), E.chain(x => t.strict({ [k]: vc }).validate(x, ctx)), E.map(x => Sum.deserialize(sum)([k, x[k]]))), (0, function_1.flow)(Sum.serialize, ([k, v]) => ({ [k]: vc.encode(v) })));
const getExternallyTaggedCodec = (sum) => (cs, name = "Sum") => foldToUnion(([tag, codec]) => getExternallyTaggedMemberCodec(sum)(tag)(codec, name))(cs, name);
exports.getExternallyTaggedCodec = getExternallyTaggedCodec;
const getAdjacentlyTaggedMemberCodec = (tagKey) => (valueKey) => (sum) => (tag) => (vc, name = "Sum") => new t.Type(name, (x) => (0, function_1.pipe)(unknownSerialize(x), O.exists(y => y[0] === tag && vc.is(y[1]))), (i, ctx) => (0, function_1.pipe)(t
.strict({ [tagKey]: t.literal(tag), [valueKey]: vc })
.validate(i, ctx), E.map(x => Sum.deserialize(sum)([
tag,
x[valueKey],
]))), (0, function_1.flow)(Sum.serialize, ([k, v]) => ({
[tagKey]: k,
[valueKey]: vc.encode(v),
})));
const getAdjacentlyTaggedCodec = (tagKey) => (valueKey) => (sum) => (cs, name = "Sum") => foldToUnion(([tag, codec]) => getAdjacentlyTaggedMemberCodec(tagKey)(valueKey)(sum)(tag)(codec, name))(cs, name);
exports.getAdjacentlyTaggedCodec = getAdjacentlyTaggedCodec;
const getUntaggedMemberCodec = (sum) => (k) => (c, name = "Sum") => new t.Type(name, (x) => (0, function_1.pipe)(unknownSerialize(x), O.exists(y => y[0] === k && c.is(y[1]))), (i, ctx) => (0, function_1.pipe)(c.validate(i, ctx), E.map(v => Sum.deserialize(sum)([k, v]))), (0, function_1.flow)(Sum.serialize, x => x[1], c.encode));
const getUntaggedCodec = (sum) => (cs, name = "Sum") => foldToUnion(([tag, codec]) => getUntaggedMemberCodec(sum)(tag)(codec, name))(cs, name);
exports.getUntaggedCodec = getUntaggedCodec;
const getInternallyTaggedMemberCodec = (tagKey) => (sum) => (tag) => (vc, name = "Sum") => new t.Type(name, (x) => (0, function_1.pipe)(unknownSerialize(x), O.exists(y => y[0] === tag && vc.is(y[1]))), (i, ctx) => (0, function_1.pipe)(t.type({ [tagKey]: t.literal(tag) }).validate(i, ctx), E.chain(x => vc.validate(x, ctx)), E.map(x => Sum.deserialize(sum)([tag, x]))), (0, function_1.flow)(Sum.serialize, ([k, v]) => ({
[tagKey]: k,
...vc.encode(v),
})));
const getInternallyTaggedCodec = (tagKey) => (sum) => (cs, name = "Sum") => foldToUnion(([tag, codec]) => getInternallyTaggedMemberCodec(tagKey)(sum)(tag)(codec, name))(cs, name);
exports.getInternallyTaggedCodec = getInternallyTaggedCodec;