@apoyo/decoders
Version:
Validation utilities
622 lines (610 loc) • 22.4 kB
JavaScript
// src/Errors.ts
var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
ErrorCode2["REQUIRED"] = "required";
ErrorCode2["STRING"] = "string";
ErrorCode2["STRING_LENGTH"] = "string.length";
ErrorCode2["STRING_MIN"] = "string.min";
ErrorCode2["STRING_MAX"] = "string.max";
ErrorCode2["STRING_PATTERN"] = "string.pattern";
ErrorCode2["STRING_EMAIL"] = "string.email";
ErrorCode2["STRING_UUID"] = "string.uuid";
ErrorCode2["STRING_EQUALS"] = "string.equals";
ErrorCode2["STRING_ONE_OF"] = "string.oneOf";
ErrorCode2["STRING_DATE"] = "string.date";
ErrorCode2["STRING_DATETIME"] = "string.datetime";
ErrorCode2["DATE"] = "date";
ErrorCode2["DATE_STRICT"] = "date.strict";
ErrorCode2["DATE_MIN"] = "date.min";
ErrorCode2["DATE_MAX"] = "date.max";
ErrorCode2["NUMBER"] = "number";
ErrorCode2["NUMBER_STRICT"] = "number.strict";
ErrorCode2["NUMBER_FROM_STRING"] = "number.fromString";
ErrorCode2["NUMBER_MIN"] = "number.min";
ErrorCode2["NUMBER_MAX"] = "number.max";
ErrorCode2["INT"] = "int";
ErrorCode2["INT_STRICT"] = "int.strict";
ErrorCode2["INT_FROM_STRING"] = "int.fromString";
ErrorCode2["INT_MIN"] = "int.min";
ErrorCode2["INT_MAX"] = "int.max";
ErrorCode2["BOOL"] = "bool";
ErrorCode2["BOOL_STRICT"] = "bool.strict";
ErrorCode2["BOOL_FROM_STRING"] = "bool.fromString";
ErrorCode2["BOOL_FROM_NUMBER"] = "bool.fromNumber";
ErrorCode2["BOOL_EQUALS"] = "bool.equals";
ErrorCode2["ARRAY"] = "array";
ErrorCode2["ARRAY_NON_EMPTY"] = "array.nonEmpty";
ErrorCode2["ARRAY_LENGTH"] = "array.length";
ErrorCode2["ARRAY_MIN"] = "array.min";
ErrorCode2["ARRAY_MAX"] = "array.max";
ErrorCode2["DICT"] = "dict";
ErrorCode2["ENUM"] = "enum.native";
ErrorCode2["ENUM_LITERAL"] = "enum.literal";
ErrorCode2["ENUM_IS_IN"] = "enum.isIn";
return ErrorCode2;
})(ErrorCode || {});
// src/Decoder.ts
import { pipe as pipe2, Result } from "@apoyo/std";
// src/DecodeError.ts
import { Arr, pipe, Tree } from "@apoyo/std";
var DecodeErrorTag = /* @__PURE__ */ ((DecodeErrorTag2) => {
DecodeErrorTag2["VALUE"] = "DE.Value";
DecodeErrorTag2["ARRAY"] = "DE.ArrayLike";
DecodeErrorTag2["INDEX"] = "DE.Index";
DecodeErrorTag2["OBJECT"] = "DE.ObjectLike";
DecodeErrorTag2["KEY"] = "DE.Key";
DecodeErrorTag2["UNION"] = "DE.UnionLike";
DecodeErrorTag2["MEMBER"] = "DE.Member";
return DecodeErrorTag2;
})(DecodeErrorTag || {});
var value = (value2, message, meta = {}) => ({
tag: "DE.Value" /* VALUE */,
value: value2,
message,
meta
});
var key = (key2, error) => ({
tag: "DE.Key" /* KEY */,
key: key2,
error
});
var index = (index2, error) => ({
tag: "DE.Index" /* INDEX */,
index: index2,
error
});
var member = (index2, error) => ({
tag: "DE.Member" /* MEMBER */,
index: index2,
error
});
var array = (errors) => ({
tag: "DE.ArrayLike" /* ARRAY */,
kind: "array",
errors
});
var object = (errors, name) => ({
tag: "DE.ObjectLike" /* OBJECT */,
kind: "object",
name,
errors
});
var union = (errors, name) => ({
tag: "DE.UnionLike" /* UNION */,
kind: "union",
name,
errors
});
var fold = (cases) => (err) => {
switch (err.tag) {
case "DE.Value" /* VALUE */:
return cases.value(err);
case "DE.ArrayLike" /* ARRAY */:
return cases.array(err);
case "DE.ObjectLike" /* OBJECT */:
return cases.object(err);
case "DE.UnionLike" /* UNION */:
return cases.union(err);
}
};
var toTree = fold({
value: (err) => Tree.of(`cannot decode ${JSON.stringify(err.value)}: ${err.message}`),
array: (err) => Tree.of(`${err.kind}`, pipe(err.errors, Arr.map((err2) => Tree.of(`index ${JSON.stringify(err2.index)}`, [err2.error].map(toTree))))),
object: (err) => Tree.of(`${err.kind}${err.name ? " " + err.name : ""}`, pipe(err.errors, Arr.map((err2) => Tree.of(`property ${JSON.stringify(err2.key)}`, [err2.error].map(toTree))))),
union: (err) => Tree.of(`${err.kind}${err.name ? " " + err.name : ""}`, pipe(err.errors, Arr.map((err2) => Tree.of(`member ${JSON.stringify(err2.index)}`, [err2.error].map(toTree)))))
});
var draw = (e) => pipe(e, toTree, Tree.draw);
var flatten = fold({
value: (err) => [
{
value: err.value,
message: err.message,
meta: err.meta,
path: []
}
],
array: (err) => pipe(err.errors, Arr.chain((sub) => pipe(flatten(sub.error), Arr.map((error) => ({
...error,
path: [
{
tag: "DE.ArrayLike" /* ARRAY */,
kind: err.kind
},
{
tag: "DE.Index" /* INDEX */,
index: sub.index
},
...error.path
]
}))))),
object: (err) => pipe(err.errors, Arr.chain((sub) => pipe(flatten(sub.error), Arr.map((error) => ({
...error,
path: [
{
tag: "DE.ObjectLike" /* OBJECT */,
kind: err.kind,
name: err.name
},
{
tag: "DE.Key" /* KEY */,
key: sub.key
},
...error.path
]
}))))),
union: (err) => pipe(err.errors, Arr.chain((sub) => pipe(flatten(sub.error), Arr.map((error) => ({
...error,
path: [
{
tag: "DE.UnionLike" /* UNION */,
kind: err.kind,
name: err.name
},
{
tag: "DE.Member" /* MEMBER */,
index: sub.index
},
...error.path
]
})))))
});
var formatBy = (fn) => (e) => pipe(e, flatten, Arr.map(fn));
var getDescription = (err, separator = ", at ") => {
const stack = pipe(err.path, Arr.filterMap((p) => {
if (p.tag === "DE.ArrayLike" /* ARRAY */) {
return `${p.kind}`;
}
if (p.tag === "DE.Index" /* INDEX */) {
return `index ${p.index}`;
}
if (p.tag === "DE.ObjectLike" /* OBJECT */) {
return `${p.kind}${p.name ? " " + p.name : ""}`;
}
if (p.tag === "DE.Key" /* KEY */) {
return `property ${JSON.stringify(p.key)}`;
}
if (p.tag === "DE.UnionLike" /* UNION */) {
return `${p.kind}${p.name ? " " + p.name : ""}`;
}
if (p.tag === "DE.Member" /* MEMBER */) {
return `member ${p.index}`;
}
return void 0;
}));
return pipe([`cannot decode ${JSON.stringify(err.value)}: ${err.message}`, ...stack], Arr.join(separator));
};
var toPath = (path) => pipe(path, Arr.mapIndexed((item, i) => typeof item === "number" ? `[${item}]` : i > 0 ? `.${item}` : item), Arr.join(""));
var getPath = (err) => {
return pipe(err.path, Arr.filterMap((p) => p.tag === "DE.Index" /* INDEX */ ? p.index : p.tag === "DE.Key" /* KEY */ ? p.key : void 0), toPath);
};
var getFormatted = (e) => ({
value: e.value,
message: e.message,
meta: e.meta,
description: getDescription(e),
path: getPath(e)
});
var format = formatBy(getFormatted);
var formatError = (e) => getDescription(e);
var DecodeError = {
value,
key,
index,
member,
array,
object,
union,
fold,
toTree,
draw,
flatten,
getDescription,
getPath,
getFormatted,
formatBy,
format,
formatError
};
// src/Decoder.ts
var create = (fn) => ({
decode: fn
});
var fromGuard = (fn, message, meta) => create((input) => fn(input) ? Result.ok(input) : Result.ko(DecodeError.value(input, message, meta)));
var parse = (fn) => (decoder) => create((input) => pipe2(input, validate(decoder), Result.chain(fn)));
var chain = (fn) => (decoder) => pipe2(decoder, parse((value2) => pipe2(value2, validate(fn(value2)))));
var map = (fn) => (decoder) => create((input) => pipe2(input, validate(decoder), Result.map(fn)));
var mapError = (fn) => (decoder) => create((input) => pipe2(input, validate(decoder), Result.mapError((err) => fn(err, input))));
var withMessage = (msg, meta) => (decoder) => pipe2(decoder, mapError((_, input) => DecodeError.value(input, msg, meta)));
var nullable = (decoder) => create((input) => input === null || input === void 0 ? Result.ok(null) : pipe2(input, validate(decoder)));
var optional = (decoder) => create((input) => input === void 0 ? Result.ok(void 0) : pipe2(input, validate(decoder)));
var required = (decoder) => create((input) => input === void 0 || input === null ? Result.ko(DecodeError.value(input, "input is required", { code: "required" /* REQUIRED */ })) : pipe2(input, validate(decoder)));
var guard = (fn) => parse((input) => {
const error = fn(input);
return error !== void 0 ? Result.ko(error) : Result.ok(input);
});
function filter(fn, message, meta = {}) {
return parse((input) => fn(input) ? Result.ok(input) : Result.ko(DecodeError.value(input, message, meta)));
}
function reject(fn, message, meta = {}) {
return parse((input) => !fn(input) ? Result.ok(input) : Result.ko(DecodeError.value(input, message, meta)));
}
var ref = (decoder) => decoder;
function validate(decoder) {
return (input) => decoder.decode(input);
}
var lazy = (fn) => create((input) => pipe2(input, validate(fn())));
function defaultValue(value2) {
return (decoder) => pipe2(decoder, optional, map((input) => input === void 0 ? value2 : input));
}
function union2(...members) {
return create((input) => pipe2(members, Result.unionBy((member2, index2) => pipe2(input, Decoder.validate(member2), Result.mapError((err) => DecodeError.member(index2, err)))), Result.mapError(DecodeError.union)));
}
var any = create(Result.ok);
var unknown = create(Result.ok);
var Decoder = {
create,
fromGuard,
map,
mapError,
withMessage,
parse,
chain,
guard,
filter,
reject,
nullable,
optional,
required,
lazy,
default: defaultValue,
union: union2,
ref,
validate,
unknown,
any
};
// src/TextDecoder.ts
import { flow, pipe as pipe3, Str } from "@apoyo/std";
var REGEXP_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
var REGEXP_EMAIL = /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
var REGEXP_DATE = /^([0-9]{4}[-](0?[1-9]|1[0-2])[-](0?[1-9]|[12][0-9]|3[01]))$/;
var REGEXP_DATETIME = /^([0-9]{4}[-](0?[1-9]|1[0-2])[-](0?[1-9]|[12][0-9]|3[01]))[T ]((0?[1-9]|[1][0-9]|2[0-3]):([0-5][0-9])(:([0-5][0-9])(\.\d+)?)?)Z?$/;
var string = Decoder.fromGuard((input) => typeof input === "string", `value is not a string`, {
code: "string" /* STRING */
});
var length = (len) => Decoder.filter((input) => input.length === len, `string should contain exactly ${len} characters`, {
code: "string.length" /* STRING_LENGTH */,
length: len
});
var min = (minLength) => Decoder.filter((input) => input.length >= minLength, `string should contain at least ${minLength} characters`, {
code: "string.min" /* STRING_MIN */,
minLength
});
var max = (maxLength) => Decoder.filter((input) => input.length <= maxLength, `string should contain at most ${maxLength} characters`, {
code: "string.max" /* STRING_MAX */,
maxLength
});
var between = (minLength, maxLength) => flow(min(minLength), max(maxLength));
var varchar = (minLength, maxLength) => pipe3(string, between(minLength, maxLength));
var nullable2 = flow(Decoder.map((str) => str.length === 0 ? null : str), Decoder.nullable);
var optional2 = flow(Decoder.map((str) => str.length === 0 ? void 0 : str), Decoder.optional);
var trim = Decoder.map(Str.trim);
var htmlEscape = Decoder.map(Str.htmlEscape);
var pattern = (regexp, message = "string does not match the given pattern", meta = {}) => Decoder.filter((value2) => regexp.test(value2), message, {
code: "string.pattern" /* STRING_PATTERN */,
...meta
});
var date = pipe3(string, pattern(REGEXP_DATE, `string is not a date string`, {
code: "string.date" /* STRING_DATE */
}));
var datetime = pipe3(string, pattern(REGEXP_DATETIME, `string is not a datetime string`, {
code: "string.datetime" /* STRING_DATETIME */
}));
var email = pipe3(string, pattern(REGEXP_EMAIL, `string is not an email`, {
code: "string.email" /* STRING_EMAIL */
}));
var uuid = pipe3(string, pattern(REGEXP_UUID, `string is not an uuid`, {
code: "string.uuid" /* STRING_UUID */
}));
var equals = (value2) => pipe3(string, Decoder.filter((str) => str === value2, `string is not equal to value ${JSON.stringify(value2)}`, {
code: "string.equals" /* STRING_EQUALS */
}));
function oneOf(arr) {
const set = new Set(arr);
return pipe3(string, Decoder.filter((str) => set.has(str), `string is not included in the given values`, {
code: "string.oneOf" /* STRING_ONE_OF */,
values: arr
}));
}
var TextDecoder = {
string,
length,
min,
max,
between,
trim,
pattern,
date,
datetime,
email,
uuid,
varchar,
nullable: nullable2,
optional: optional2,
oneOf,
equals,
htmlEscape
};
// src/NumberDecoder.ts
import { flow as flow2, pipe as pipe4 } from "@apoyo/std";
var strict = Decoder.fromGuard((input) => typeof input === "number" && !Number.isNaN(input), `value is not a number`, {
code: "number.strict" /* NUMBER_STRICT */
});
var fromString = pipe4(TextDecoder.string, Decoder.map(parseFloat), Decoder.chain(() => strict), Decoder.withMessage(`could not parse input string into a number`, {
code: "number.fromString" /* NUMBER_FROM_STRING */
}));
var number = pipe4(Decoder.union(strict, fromString), Decoder.withMessage(`value is not a number`, {
code: "number" /* NUMBER */
}));
var min2 = (minimum) => Decoder.filter((input) => input >= minimum, `number should be greater or equal than ${minimum}`, {
code: "number.min" /* NUMBER_MIN */,
minimum
});
var max2 = (maximum) => Decoder.filter((input) => input <= maximum, `number should be lower or equal than ${maximum}`, {
code: "number.max" /* NUMBER_MAX */,
maximum
});
var between2 = (minimum, maximum) => flow2(min2(minimum), max2(maximum));
var range = (minimum, maximum) => pipe4(number, between2(minimum, maximum));
var NumberDecoder = {
strict,
number,
min: min2,
max: max2,
between: between2,
range,
fromString
};
// src/IntegerDecoder.ts
import { pipe as pipe5 } from "@apoyo/std";
var strict2 = pipe5(NumberDecoder.strict, Decoder.filter((nb) => nb % 1 === 0, `number is not a integer`, {
code: "int.strict" /* INT_STRICT */
}));
var fromString2 = pipe5(NumberDecoder.fromString, Decoder.chain(() => strict2), Decoder.withMessage(`could not parse input string into an integer`, {
code: "int.fromString" /* INT_FROM_STRING */
}));
var int = pipe5(Decoder.union(strict2, fromString2), Decoder.withMessage(`value is not a integer`, {
code: "int" /* INT */
}));
var min3 = NumberDecoder.min;
var max3 = NumberDecoder.max;
var between3 = NumberDecoder.between;
var positive = pipe5(int, min3(0));
var range2 = (minimum, maximum) => pipe5(int, between3(minimum, maximum));
var IntegerDecoder = {
strict: strict2,
int,
min: min3,
max: max3,
between: between3,
range: range2,
positive,
fromString: fromString2
};
// src/BooleanDecoder.ts
import { pipe as pipe6, Result as Result2 } from "@apoyo/std";
var TEXT_TRUE = /* @__PURE__ */ new Set(["true", "yes", "y", "1"]);
var TEXT_FALSE = /* @__PURE__ */ new Set(["false", "no", "no", "0"]);
var strict3 = Decoder.fromGuard((input) => typeof input === "boolean", `value is not a boolean`, {
code: "bool.strict" /* BOOL_STRICT */
});
var fromString3 = pipe6(TextDecoder.string, Decoder.parse((str) => {
const low = str.toLowerCase();
return TEXT_TRUE.has(low) ? Result2.ok(true) : TEXT_FALSE.has(low) ? Result2.ok(false) : Result2.ko(DecodeError.value(str, `string is not a boolean`));
}), Decoder.withMessage(`could not parse input string into a boolean`, {
code: "bool.fromString" /* BOOL_FROM_STRING */
}));
var fromNumber = pipe6(IntegerDecoder.strict, Decoder.parse((nb) => nb === 1 ? Result2.ok(true) : nb === 0 ? Result2.ok(false) : Result2.ko(DecodeError.value(nb, `number is not a boolean`))), Decoder.withMessage(`could not parse input number into a boolean`, {
code: "bool.fromNumber" /* BOOL_FROM_NUMBER */
}));
var boolean = pipe6(Decoder.union(strict3, fromString3, fromNumber), Decoder.withMessage(`value is not a boolean`, {
code: "bool" /* BOOL */
}));
var equals2 = (bool) => pipe6(boolean, Decoder.filter((value2) => value2 === bool, `boolean is not ${bool}`, {
code: "bool.equals" /* BOOL_EQUALS */
}));
var BooleanDecoder = {
strict: strict3,
boolean,
equals: equals2,
fromString: fromString3,
fromNumber
};
// src/ObjectDecoder.ts
import { Dict as Dict3, Obj, pipe as pipe7, Result as Result3 } from "@apoyo/std";
var create2 = (props, decoder) => ({
props,
...decoder
});
var unknownDict = Decoder.fromGuard((input) => typeof input === "object" && input !== null && !Array.isArray(input), `value is not an object`, {
code: "dict" /* DICT */
});
var dict = (decoder) => {
return pipe7(unknownDict, Decoder.parse((input) => pipe7(input, Result3.structBy((value2, key2) => pipe7(value2, Decoder.validate(decoder), Result3.mapError((err) => DecodeError.key(key2, err)))), Result3.mapError((errors) => DecodeError.object(errors)))));
};
var struct = (props, name) => {
return create2(props, pipe7(unknownDict, Decoder.parse((input) => pipe7(props, Result3.structBy((prop, key2) => pipe7(input[key2], Decoder.validate(prop), Result3.mapError((err) => DecodeError.key(key2, err)))), Result3.map(Dict3.compact), Result3.mapError((errors) => DecodeError.object(errors, name))))));
};
var guard2 = (fn) => (decoder) => create2(decoder.props, pipe7(decoder, Decoder.guard(fn)));
function omit(props) {
return (decoder) => pipe7(decoder.props, Obj.omit(props), struct);
}
function pick(props) {
return (decoder) => pipe7(decoder.props, Obj.pick(props), struct);
}
function partial(decoder) {
return pipe7(decoder.props, Dict3.map(Decoder.optional), struct);
}
function merge(...members) {
return struct(Object.assign({}, ...members.map((m) => m.props)));
}
function sum(prop, cases) {
const keys = Dict3.keys(cases);
const typeDecoder = TextDecoder.oneOf(keys);
return pipe7(unknownDict, Decoder.parse((input) => pipe7(input[prop], Decoder.validate(typeDecoder), Result3.chain((type) => pipe7(input, Decoder.validate(cases[type]), Result3.map((parsed) => ({
[prop]: type,
...parsed
})))))));
}
var additionalProperties = (decoder) => pipe7(unknownDict, Decoder.parse((input) => pipe7(input, Decoder.validate(decoder), Result3.map((parsed) => ({
...input,
...parsed
})))));
var ObjectDecoder = {
unknownDict,
dict,
struct,
omit,
pick,
partial,
guard: guard2,
merge,
additionalProperties,
sum
};
// src/ArrayDecoder.ts
import { Arr as Arr2, flow as flow3, pipe as pipe8, Result as Result4 } from "@apoyo/std";
var unknownArray = Decoder.fromGuard(Arr2.isArray, `value is not an array`, {
code: "array" /* ARRAY */
});
var array2 = (decoder) => pipe8(unknownArray, Decoder.parse((input) => pipe8(input, Arr2.mapIndexed((value2, index2) => pipe8(value2, Decoder.validate(decoder), Result4.mapError((err) => DecodeError.index(index2, err)))), Arr2.separate, ([success, errors]) => errors.length > 0 ? Result4.ko(DecodeError.array(errors)) : Result4.ok(success))));
var nonEmptyArray = (decoder) => pipe8(array2(decoder), Decoder.filter(Arr2.isNonEmpty, `array should not be empty`, {
code: "array.nonEmpty" /* ARRAY_NON_EMPTY */
}));
var length2 = (len) => Decoder.filter((arr) => arr.length === len, `array should contain exactly ${len} elements`, {
code: "array.length" /* ARRAY_LENGTH */,
length: len
});
var min4 = (minLength) => Decoder.filter((arr) => arr.length >= minLength, `array should contain at least ${minLength} elements`, {
code: "array.min" /* ARRAY_MIN */,
minLength
});
var max4 = (maxLength) => Decoder.filter((arr) => arr.length <= maxLength, `array should contain at most ${maxLength} elements`, {
code: "array.max" /* ARRAY_MAX */,
maxLength
});
var between4 = (minLength, maxLength) => flow3(min4(minLength), max4(maxLength));
var ArrayDecoder = {
unknownArray,
array: array2,
nonEmptyArray,
length: length2,
min: min4,
max: max4,
between: between4
};
// src/DateDecoder.ts
import { pipe as pipe9, Result as Result5 } from "@apoyo/std";
var isValid = Decoder.filter((date3) => !Number.isNaN(date3.getTime()), `string is not a valid Date`, {
code: "date" /* DATE */
});
var createDateDecoder = (decoder) => {
const fromString4 = pipe9(decoder, Decoder.map((str) => new Date(str)));
return pipe9(Decoder.union(strict4, fromString4), isValid);
};
var strict4 = Decoder.fromGuard((input) => input instanceof Date, `input is not a Date object`, {
code: "date.strict" /* DATE_STRICT */
});
var date2 = createDateDecoder(TextDecoder.date);
var datetime2 = createDateDecoder(TextDecoder.datetime);
var native = createDateDecoder(TextDecoder.string);
var min5 = (minDate) => Decoder.parse((input) => {
const min6 = typeof minDate === "function" ? minDate() : minDate;
return input.getTime() >= min6.getTime() ? Result5.ok(input) : Result5.ko(DecodeError.value(input, `date should be above ${min6.toISOString()}`, {
code: "date.min" /* DATE_MIN */,
min: min6
}));
});
var max5 = (maxDate) => Decoder.parse((input) => {
const max6 = typeof maxDate === "function" ? maxDate() : maxDate;
return input.getTime() <= max6.getTime() ? Result5.ok(input) : Result5.ko(DecodeError.value(input, `date should be below ${max6.toISOString()}`, {
code: "date.max" /* DATE_MAX */,
max: max6
}));
});
var DateDecoder = {
date: date2,
datetime: datetime2,
strict: strict4,
native,
min: min5,
max: max5
};
// src/EnumDecoder.ts
import { Enum } from "@apoyo/std";
var create3 = (values, decoder) => ({
...decoder,
values
});
var inSet = (set) => (value2) => set.has(value2);
var native2 = (enumType) => {
const values = Enum.values(enumType);
const set = new Set(values);
return create3(set, Decoder.fromGuard(inSet(set), `input does not match any value in enumeration`, {
code: "enum.native" /* ENUM */,
values
}));
};
var from = native2;
var literal = (...values) => {
const set = new Set(values);
return create3(set, Decoder.fromGuard(inSet(set), `value is not equal to ${values.join(", or ")}`, {
code: "enum.literal" /* ENUM_LITERAL */,
values
}));
};
function isIn(arr) {
const set = arr instanceof Set ? arr : new Set(arr);
return create3(set, Decoder.fromGuard(inSet(set), `string is not included in the allowed list of values`, {
code: "enum.isIn" /* ENUM_IS_IN */
}));
}
var EnumDecoder = {
native: native2,
from,
literal,
isIn
};
export {
ArrayDecoder,
BooleanDecoder,
DateDecoder,
DecodeError,
DecodeErrorTag,
Decoder,
EnumDecoder,
ErrorCode,
IntegerDecoder,
NumberDecoder,
ObjectDecoder,
TextDecoder
};