validation.ts
Advanced tools
Comparing version 0.0.27 to 0.0.28
@@ -1,5 +0,4 @@ | ||
import { Result, Ok, Err, Option, None, Some } from 'space-lift'; | ||
export declare abstract class Validator<T> { | ||
export interface Validator<T> { | ||
readonly T: T; | ||
abstract validate(value: Value, config?: Configuration, context?: Context): Validation<T>; | ||
validate(value: Value, config?: Configuration, context?: Context): Validation<T>; | ||
map<B>(fn: (value: T) => B): Validator<B>; | ||
@@ -12,2 +11,20 @@ filter(fn: (value: T) => boolean): Validator<T>; | ||
} | ||
export declare type Ok<VALUE> = { | ||
type: 'ok'; | ||
value: VALUE; | ||
}; | ||
export declare type Err<ERROR> = { | ||
type: 'error'; | ||
errors: ERROR; | ||
}; | ||
export declare type Result<ERROR, VALUE> = Err<ERROR> | Ok<VALUE>; | ||
export declare function Ok<VALUE>(value: VALUE): { | ||
readonly type: "ok"; | ||
readonly value: VALUE; | ||
}; | ||
export declare function Err<ERROR>(errors: ERROR): { | ||
readonly type: "error"; | ||
readonly errors: ERROR; | ||
}; | ||
export declare function isOk<VALUE>(result: Result<unknown, VALUE>): result is Ok<VALUE>; | ||
export declare type Any = Validator<Value>; | ||
@@ -29,41 +46,18 @@ export declare type TypeOf<V extends Any> = V['T']; | ||
export declare function failure(context: Context, message: string): Validation<never>; | ||
export declare function typeFailure(value: any, context: Context, expectedType: string): Result<{ | ||
context: Context; | ||
message: string; | ||
}[], never>; | ||
export declare function typeFailure(value: any, context: Context, expectedType: string): { | ||
readonly type: "error"; | ||
readonly errors: { | ||
context: Context; | ||
message: string; | ||
}[]; | ||
}; | ||
export declare function getContext(name: string, parent?: string): Context; | ||
export declare const snakeCaseTransformation: (key: string) => string; | ||
export declare function is<T>(value: Value, validator: Validator<T>): value is T; | ||
export declare class NullValidator extends Validator<null> { | ||
validate(v: Value, _config?: Configuration, c?: Context): Result<ValidationError[], null>; | ||
} | ||
export declare class UndefinedValidator extends Validator<undefined> { | ||
validate(v: Value, _config?: Configuration, c?: Context): Result<ValidationError[], undefined>; | ||
} | ||
export declare class StringValidator extends Validator<string> { | ||
validate(v: Value, _config?: Configuration, c?: Context): Result<ValidationError[], string>; | ||
} | ||
export declare class NumberValidator extends Validator<number> { | ||
validate(v: Value, _config?: Configuration, c?: Context): Result<ValidationError[], number>; | ||
} | ||
export declare class BooleanValidator extends Validator<boolean> { | ||
validate(v: Value, _config?: Configuration, c?: Context): Result<ValidationError[], boolean>; | ||
} | ||
export declare class TransformValidator<A, B> extends Validator<B> { | ||
private validator; | ||
private f; | ||
constructor(validator: Validator<A>, f: (a: Validation<A>) => Result<string | ValidationError[], B>); | ||
validate(v: Value, config?: Configuration, c?: Context): Result<ValidationError[], B>; | ||
} | ||
export declare class ArrayValidator<A> extends Validator<A[]> { | ||
private validator; | ||
constructor(validator: Validator<A>); | ||
validate(v: Value, config?: Configuration, c?: Context): Ok<ValidationError[], never> | Err<ValidationError[], never> | Ok<never, A[]> | Err<never, A[]>; | ||
} | ||
declare const nullValidator: Validator<null>; | ||
declare const undefinedValidator: Validator<undefined>; | ||
export declare const string: Validator<string>; | ||
export declare const number: Validator<number>; | ||
export declare const boolean: Validator<boolean>; | ||
export declare function array<A>(validator: Validator<A>): Validator<A[]>; | ||
export declare class TupleValidator extends Validator<any> { | ||
private validators; | ||
constructor(validators: Validator<any>[]); | ||
validate(v: Value, config?: Configuration, c?: Context): Ok<ValidationError[], never> | Err<ValidationError[], never> | Ok<never, any[]> | Err<never, any[]>; | ||
} | ||
export declare function tuple<A = never>(): Validator<A[]>; | ||
@@ -97,20 +91,6 @@ export declare function tuple<A>(a: Validator<A>): Validator<[A]>; | ||
}; | ||
export declare class ObjectValidator<P extends Props> extends Validator<ObjectOf<P>> { | ||
export declare function object<P extends Props>(props: P): Validator<ObjectOf<P>> & { | ||
props: P; | ||
constructor(props: P); | ||
validate(v: Value, config?: Configuration, c?: Context): Validation<ObjectOf<P>>; | ||
} | ||
export declare function object<P extends Props>(props: P): ObjectValidator<P>; | ||
export declare class KeyOfValidator<KEYS extends object> extends Validator<keyof KEYS> { | ||
private keys; | ||
constructor(keys: KEYS); | ||
validate(v: Value, _config?: Configuration, c?: Context): Validation<keyof KEYS>; | ||
} | ||
export declare function keyof<KEYS extends object>(keys: KEYS): KeyOfValidator<KEYS>; | ||
export declare class DictionaryValidator<K extends string, V> extends Validator<Record<K, V>> { | ||
private domain; | ||
private codomain; | ||
constructor(domain: Validator<K>, codomain: Validator<V>); | ||
validate(v: Value, config?: Configuration, c?: Context): Ok<ValidationError[], never> | Err<ValidationError[], never> | Ok<never, any> | Err<never, any>; | ||
} | ||
}; | ||
export declare function keyof<KEYS extends object>(keys: KEYS): Validator<keyof KEYS>; | ||
export declare function dictionary<K extends string, V>(domain: Validator<K>, codomain: Validator<V>): Validator<Record<K, V>>; | ||
@@ -125,12 +105,2 @@ export declare type Literal = string | number | boolean | null | undefined; | ||
export declare function intersection<A, B, C, D, E, F>(a: Validator<A>, b: Validator<B>, c: Validator<C>, d: Validator<D>, e: Validator<E>, f: Validator<F>): Validator<A & B & C & D & E & F>; | ||
export declare class UnionValidator<A> extends Validator<A> { | ||
private validators; | ||
constructor(validators: Validator<A>[]); | ||
validate(v: Value, config?: Configuration, c?: Context): Err<ValidationError[], never> | Ok<ValidationError[], A>; | ||
} | ||
export declare class LiteralUnionValidator<A extends Literal> extends Validator<A> { | ||
private values; | ||
constructor(values: A[]); | ||
validate(v: Value, config?: Configuration, c?: Context): Err<ValidationError[], never> | Ok<ValidationError[], A>; | ||
} | ||
export declare function union<A, B>(a: Validator<A>, b: Validator<B>): Validator<A | B>; | ||
@@ -154,22 +124,6 @@ export declare function union<A extends Literal, B extends Literal>(a: A, b: B): Validator<A | B>; | ||
export declare function union<A extends Literal, B extends Literal, C extends Literal, D extends Literal, E extends Literal, F extends Literal, G extends Literal, H extends Literal, I extends Literal, J extends Literal>(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J): Validator<A | B | C | D | E | F | G | H | I | J>; | ||
export declare class OptionalValidator<V> extends Validator<V | undefined> { | ||
private validator; | ||
constructor(validator: Validator<V>); | ||
validate(v: Value, config?: Configuration, c?: Context): Ok<ValidationError[], undefined> | Err<ValidationError[], undefined> | Ok<ValidationError[], V> | Err<ValidationError[], V>; | ||
} | ||
export declare function optional<V>(validator: Validator<V>): Validator<V | undefined>; | ||
export declare class OptionValidator<V> extends Validator<Option<V>> { | ||
private validator; | ||
constructor(validator: Validator<V>); | ||
validate(v: Value, config?: Configuration, c?: Context): Ok<ValidationError[], None> | Err<ValidationError[], None> | Ok<ValidationError[], Some<V>> | Err<ValidationError[], Some<V>>; | ||
} | ||
export declare function option<V>(validator: Validator<V>): Validator<Option<V>>; | ||
export declare function recursion<T>(definition: (self: Validator<T>) => Any): Validator<T>; | ||
export declare const isoDate: Validator<Date>; | ||
export declare function errorDebugString(errors: ValidationError[]): string; | ||
declare const nullValidator: NullValidator; | ||
declare const undefinedValidator: UndefinedValidator; | ||
export { nullValidator as null, undefinedValidator as undefined }; | ||
export declare const string: StringValidator; | ||
export declare const number: NumberValidator; | ||
export declare const boolean: BooleanValidator; | ||
export declare const isoDate: Validator<Date>; |
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
//-------------------------------------- | ||
// Setup | ||
//-------------------------------------- | ||
var __assign = (this && this.__assign) || function () { | ||
@@ -26,35 +16,53 @@ __assign = Object.assign || function(t) { | ||
}; | ||
exports.__esModule = true; | ||
var space_lift_1 = require("space-lift"); | ||
//-------------------------------------- | ||
// Setup | ||
//-------------------------------------- | ||
var Validator = /** @class */ (function () { | ||
function Validator() { | ||
this.T = null; // Phantom type | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.undefined = exports.null = exports.errorDebugString = exports.isoDate = exports.recursion = exports.optional = exports.union = exports.intersection = exports.literal = exports.dictionary = exports.keyof = exports.object = exports.tuple = exports.array = exports.boolean = exports.number = exports.string = exports.is = exports.snakeCaseTransformation = exports.getContext = exports.typeFailure = exports.failure = exports.success = exports.isOk = exports.Err = exports.Ok = void 0; | ||
var validatorMethods = { | ||
map: function (fn) { | ||
return this.flatMap(function (v) { return Ok(fn(v)); }); | ||
}, | ||
filter: function (fn) { | ||
return this.flatMap(function (v) { return fn(v) ? Ok(v) : Err("filter error: " + pretty(v) + "\""); }); | ||
}, | ||
flatMap: function (fn) { | ||
return this.transform(function (r) { return isOk(r) ? fn(r.value) : r; }); | ||
}, | ||
transform: function (fn) { | ||
var validator = this; | ||
return Object.assign({}, validatorMethods, { | ||
validate: function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
var validated = validator.validate(v, config, c); | ||
var transformed = fn(validated); | ||
if (isOk(transformed)) | ||
return success(transformed.value); | ||
var error = transformed.errors; | ||
if (typeof error === 'string') | ||
return failure(c, error); | ||
return Err(error); | ||
} | ||
}); | ||
}, | ||
tagged: function () { | ||
return this; | ||
} | ||
Validator.prototype.map = function (fn) { | ||
return this.flatMap(function (v) { return space_lift_1.Ok(fn(v)); }); | ||
}; | ||
Validator.prototype.filter = function (fn) { | ||
return this.flatMap(function (v) { return fn(v) ? space_lift_1.Ok(v) : space_lift_1.Err("The value " + pretty(v) + " failed a predicate\""); }); | ||
}; | ||
Validator.prototype.flatMap = function (fn) { | ||
return this.transform(function (r) { return r.isOk() ? fn(r.get()) : r; }); | ||
}; | ||
Validator.prototype.transform = function (fn) { | ||
return new TransformValidator(this, fn); | ||
}; | ||
Validator.prototype.tagged = function () { | ||
return this; | ||
}; | ||
return Validator; | ||
}()); | ||
exports.Validator = Validator; | ||
}; | ||
function Ok(value) { | ||
return { type: 'ok', value: value }; | ||
} | ||
exports.Ok = Ok; | ||
function Err(errors) { | ||
return { type: 'error', errors: errors }; | ||
} | ||
exports.Err = Err; | ||
function isOk(result) { | ||
return result.type === 'ok'; | ||
} | ||
exports.isOk = isOk; | ||
function success(value) { | ||
return space_lift_1.Ok(value); | ||
return Ok(value); | ||
} | ||
exports.success = success; | ||
function failure(context, message) { | ||
return space_lift_1.Err([{ context: context, message: message }]); | ||
return Err([{ context: context, message: message }]); | ||
} | ||
@@ -70,4 +78,4 @@ exports.failure = failure; | ||
})(); | ||
var message = "Type error: expected " + expectedType + " but got " + valueType; | ||
return space_lift_1.Err([{ context: context, message: message }]); | ||
var message = "Expected " + expectedType + ", got " + valueType; | ||
return Err([{ context: context, message: message }]); | ||
} | ||
@@ -90,3 +98,3 @@ exports.typeFailure = typeFailure; | ||
function is(value, validator) { | ||
return validator.validate(value).isOk(); | ||
return isOk(validator.validate(value)); | ||
} | ||
@@ -97,163 +105,54 @@ exports.is = is; | ||
//-------------------------------------- | ||
var NullValidator = /** @class */ (function (_super) { | ||
__extends(NullValidator, _super); | ||
function NullValidator() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
NullValidator.prototype.validate = function (v, _config, c) { | ||
var nullValidator = __assign({ validate: function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return v === null ? success(v) : typeFailure(v, c, 'null'); | ||
}; | ||
return NullValidator; | ||
}(Validator)); | ||
exports.NullValidator = NullValidator; | ||
var UndefinedValidator = /** @class */ (function (_super) { | ||
__extends(UndefinedValidator, _super); | ||
function UndefinedValidator() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
UndefinedValidator.prototype.validate = function (v, _config, c) { | ||
} }, validatorMethods); | ||
exports.null = nullValidator; | ||
var undefinedValidator = __assign({ validate: function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return v === void 0 ? success(v) : typeFailure(v, c, 'undefined'); | ||
}; | ||
return UndefinedValidator; | ||
}(Validator)); | ||
exports.UndefinedValidator = UndefinedValidator; | ||
var StringValidator = /** @class */ (function (_super) { | ||
__extends(StringValidator, _super); | ||
function StringValidator() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
StringValidator.prototype.validate = function (v, _config, c) { | ||
} }, validatorMethods); | ||
exports.undefined = undefinedValidator; | ||
exports.string = __assign({ validate: function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return typeof v === 'string' ? success(v) : typeFailure(v, c, 'string'); | ||
}; | ||
return StringValidator; | ||
}(Validator)); | ||
exports.StringValidator = StringValidator; | ||
var NumberValidator = /** @class */ (function (_super) { | ||
__extends(NumberValidator, _super); | ||
function NumberValidator() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
NumberValidator.prototype.validate = function (v, _config, c) { | ||
} }, validatorMethods); | ||
exports.number = __assign({ validate: function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return typeof v === 'number' ? success(v) : typeFailure(v, c, 'number'); | ||
}; | ||
return NumberValidator; | ||
}(Validator)); | ||
exports.NumberValidator = NumberValidator; | ||
var BooleanValidator = /** @class */ (function (_super) { | ||
__extends(BooleanValidator, _super); | ||
function BooleanValidator() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
BooleanValidator.prototype.validate = function (v, _config, c) { | ||
} }, validatorMethods); | ||
exports.boolean = __assign({ validate: function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return typeof v === 'boolean' ? success(v) : typeFailure(v, c, 'boolean'); | ||
}; | ||
return BooleanValidator; | ||
}(Validator)); | ||
exports.BooleanValidator = BooleanValidator; | ||
} }, validatorMethods); | ||
//-------------------------------------- | ||
// transform | ||
//-------------------------------------- | ||
var TransformValidator = /** @class */ (function (_super) { | ||
__extends(TransformValidator, _super); | ||
function TransformValidator(validator, f) { | ||
var _this = _super.call(this) || this; | ||
_this.validator = validator; | ||
_this.f = f; | ||
return _this; | ||
} | ||
TransformValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
var validated = this.validator.validate(v, config, c); | ||
var transformed = this.f(validated); | ||
if (transformed.isOk()) | ||
return success(transformed.get()); | ||
var error = transformed.get(); | ||
if (typeof error === 'string') | ||
return failure(c, error); | ||
return space_lift_1.Err(error); | ||
}; | ||
return TransformValidator; | ||
}(Validator)); | ||
exports.TransformValidator = TransformValidator; | ||
//-------------------------------------- | ||
// array | ||
//-------------------------------------- | ||
var ArrayValidator = /** @class */ (function (_super) { | ||
__extends(ArrayValidator, _super); | ||
function ArrayValidator(validator) { | ||
var _this = _super.call(this) || this; | ||
_this.validator = validator; | ||
return _this; | ||
} | ||
ArrayValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (!Array.isArray(v)) | ||
return typeFailure(v, c, 'array'); | ||
var validatedArray = []; | ||
var errors = []; | ||
for (var i = 0; i < v.length; i++) { | ||
var item = v[i]; | ||
var validation = this.validator.validate(item, config, getContext(String(i), c)); | ||
if (validation.isOk()) { | ||
validatedArray.push(validation.get()); | ||
function array(validator) { | ||
return __assign({ validate: function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (!Array.isArray(v)) | ||
return typeFailure(v, c, 'array'); | ||
var validatedArray = []; | ||
var errors = []; | ||
for (var i = 0; i < v.length; i++) { | ||
var item = v[i]; | ||
var validation = validator.validate(item, config, getContext(String(i), c)); | ||
if (isOk(validation)) { | ||
validatedArray.push(validation.value); | ||
} | ||
else { | ||
pushAll(errors, validation.errors); | ||
} | ||
} | ||
else { | ||
pushAll(errors, validation.get()); | ||
} | ||
} | ||
return errors.length ? space_lift_1.Err(errors) : space_lift_1.Ok(validatedArray); | ||
}; | ||
return ArrayValidator; | ||
}(Validator)); | ||
exports.ArrayValidator = ArrayValidator; | ||
function array(validator) { | ||
return new ArrayValidator(validator); | ||
return errors.length ? Err(errors) : Ok(validatedArray); | ||
} }, validatorMethods); | ||
} | ||
exports.array = array; | ||
//-------------------------------------- | ||
// tuple | ||
//-------------------------------------- | ||
var TupleValidator = /** @class */ (function (_super) { | ||
__extends(TupleValidator, _super); | ||
function TupleValidator(validators) { | ||
var _this = _super.call(this) || this; | ||
_this.validators = validators; | ||
return _this; | ||
} | ||
TupleValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (!Array.isArray(v)) | ||
return typeFailure(v, c, 'Tuple'); | ||
if (v.length !== this.validators.length) | ||
return failure(c, "Expected Tuple" + this.validators.length + ", got Tuple" + v.length); | ||
var validatedArray = []; | ||
var errors = []; | ||
for (var i = 0; i < v.length; i++) { | ||
var item = v[i]; | ||
var validation = this.validators[i].validate(item, config, getContext(String(i), c)); | ||
if (validation.isOk()) { | ||
validatedArray.push(validation.get()); | ||
} | ||
else { | ||
pushAll(errors, validation.get()); | ||
} | ||
} | ||
return errors.length ? space_lift_1.Err(errors) : space_lift_1.Ok(validatedArray); | ||
}; | ||
return TupleValidator; | ||
}(Validator)); | ||
exports.TupleValidator = TupleValidator; | ||
function tuple() { | ||
@@ -264,41 +163,51 @@ var validators = []; | ||
} | ||
return new TupleValidator(validators); | ||
return __assign({ validate: function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (!Array.isArray(v)) | ||
return typeFailure(v, c, 'Tuple'); | ||
if (v.length !== validators.length) | ||
return failure(c, "Expected Tuple" + validators.length + ", got Tuple" + v.length); | ||
var validatedArray = []; | ||
var errors = []; | ||
for (var i = 0; i < v.length; i++) { | ||
var item = v[i]; | ||
var validation = validators[i].validate(item, config, getContext(String(i), c)); | ||
if (isOk(validation)) { | ||
validatedArray.push(validation.value); | ||
} | ||
else { | ||
pushAll(errors, validation.errors); | ||
} | ||
} | ||
return errors.length ? Err(errors) : Ok(validatedArray); | ||
} }, validatorMethods); | ||
} | ||
exports.tuple = tuple; | ||
var ObjectValidator = /** @class */ (function (_super) { | ||
__extends(ObjectValidator, _super); | ||
function ObjectValidator(props) { | ||
var _this = _super.call(this) || this; | ||
_this.props = props; | ||
return _this; | ||
} | ||
ObjectValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (v == null || typeof v !== 'object') | ||
return typeFailure(v, c, 'object'); | ||
var validatedObject = {}; | ||
var errors = []; | ||
for (var key in this.props) { | ||
var transformedKey = config.transformObjectKeys !== undefined | ||
? config.transformObjectKeys(key) | ||
: key; | ||
var value = v[transformedKey]; | ||
var validator = this.props[key]; | ||
var validation = validator.validate(value, config, getContext(transformedKey, c)); | ||
if (validation.isOk()) { | ||
if (validation.get() !== undefined) | ||
validatedObject[key] = validation.get(); | ||
function object(props) { | ||
return __assign({ props: props, | ||
validate: function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (v == null || typeof v !== 'object') | ||
return typeFailure(v, c, 'object'); | ||
var validatedObject = {}; | ||
var errors = []; | ||
for (var key in props) { | ||
var transformedKey = config.transformObjectKeys !== undefined | ||
? config.transformObjectKeys(key) | ||
: key; | ||
var value = v[transformedKey]; | ||
var validator = props[key]; | ||
var validation = validator.validate(value, config, getContext(transformedKey, c)); | ||
if (isOk(validation)) { | ||
if (validation.value !== undefined) | ||
validatedObject[key] = validation.value; | ||
} | ||
else { | ||
pushAll(errors, validation.errors); | ||
} | ||
} | ||
else { | ||
pushAll(errors, validation.get()); | ||
} | ||
} | ||
return errors.length ? space_lift_1.Err(errors) : space_lift_1.Ok(validatedObject); | ||
}; | ||
return ObjectValidator; | ||
}(Validator)); | ||
exports.ObjectValidator = ObjectValidator; | ||
function object(props) { | ||
return new ObjectValidator(props); | ||
return errors.length ? Err(errors) : Ok(validatedObject); | ||
} }, validatorMethods); | ||
} | ||
@@ -309,21 +218,10 @@ exports.object = object; | ||
//-------------------------------------- | ||
var KeyOfValidator = /** @class */ (function (_super) { | ||
__extends(KeyOfValidator, _super); | ||
function KeyOfValidator(keys) { | ||
var _this = _super.call(this) || this; | ||
_this.keys = keys; | ||
return _this; | ||
} | ||
KeyOfValidator.prototype.validate = function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return this.keys.hasOwnProperty(v) | ||
? success(v) | ||
: failure(c, pretty(v) + " is not a key of " + pretty(this.keys)); | ||
}; | ||
return KeyOfValidator; | ||
}(Validator)); | ||
exports.KeyOfValidator = KeyOfValidator; | ||
function keyof(keys) { | ||
return new KeyOfValidator(keys); | ||
return __assign({ validate: function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return keys.hasOwnProperty(v) | ||
? success(v) | ||
: failure(c, pretty(v) + " is not a key of " + pretty(keys)); | ||
} }, validatorMethods); | ||
} | ||
@@ -334,164 +232,104 @@ exports.keyof = keyof; | ||
//-------------------------------------- | ||
var DictionaryValidator = /** @class */ (function (_super) { | ||
__extends(DictionaryValidator, _super); | ||
function DictionaryValidator(domain, codomain) { | ||
var _this = _super.call(this) || this; | ||
_this.domain = domain; | ||
_this.codomain = codomain; | ||
return _this; | ||
} | ||
DictionaryValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (v == null || typeof v !== 'object') | ||
return typeFailure(v, c, 'object'); | ||
var validatedDict = {}; | ||
var errors = []; | ||
var _loop_1 = function (key) { | ||
var value = v[key]; | ||
var context = getContext(key, c); | ||
var domainValidation = this_1.domain.validate(key, config, context); | ||
var codomainValidation = this_1.codomain.validate(value, config, context); | ||
if (domainValidation.isOk()) { | ||
key = domainValidation.get(); | ||
function dictionary(domain, codomain) { | ||
return __assign({ validate: function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (v == null || typeof v !== 'object') | ||
return typeFailure(v, c, 'object'); | ||
var validatedDict = {}; | ||
var errors = []; | ||
var _loop_1 = function (key) { | ||
var value = v[key]; | ||
var context = getContext(key, c); | ||
var domainValidation = domain.validate(key, config, context); | ||
var codomainValidation = codomain.validate(value, config, context); | ||
if (isOk(domainValidation)) { | ||
key = domainValidation.value; | ||
} | ||
else { | ||
var error = domainValidation.errors; | ||
pushAll(errors, error.map(function (e) { return ({ context: context, message: "key error: " + e.message }); })); | ||
} | ||
if (isOk(codomainValidation)) { | ||
validatedDict[key] = codomainValidation.value; | ||
} | ||
else { | ||
var error = codomainValidation.errors; | ||
pushAll(errors, error.map(function (e) { return ({ context: context, message: "value error: " + e.message }); })); | ||
} | ||
}; | ||
for (var key in v) { | ||
_loop_1(key); | ||
} | ||
else { | ||
var error = domainValidation.get(); | ||
pushAll(errors, error.map(function (e) { return ({ context: context, message: "key error: " + e.message }); })); | ||
} | ||
if (codomainValidation.isOk()) { | ||
validatedDict[key] = codomainValidation.get(); | ||
} | ||
else { | ||
var error = codomainValidation.get(); | ||
pushAll(errors, error.map(function (e) { return ({ context: context, message: "value error: " + e.message }); })); | ||
} | ||
}; | ||
var this_1 = this; | ||
for (var key in v) { | ||
_loop_1(key); | ||
} | ||
return errors.length ? space_lift_1.Err(errors) : space_lift_1.Ok(validatedDict); | ||
}; | ||
return DictionaryValidator; | ||
}(Validator)); | ||
exports.DictionaryValidator = DictionaryValidator; | ||
function dictionary(domain, codomain) { | ||
return new DictionaryValidator(domain, codomain); | ||
return errors.length ? Err(errors) : Ok(validatedDict); | ||
} }, validatorMethods); | ||
} | ||
exports.dictionary = dictionary; | ||
var LiteralValidator = /** @class */ (function (_super) { | ||
__extends(LiteralValidator, _super); | ||
function LiteralValidator(value) { | ||
var _this = _super.call(this) || this; | ||
_this.value = value; | ||
return _this; | ||
} | ||
LiteralValidator.prototype.validate = function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return v === this.value | ||
? success(v) | ||
: failure(c, "Expected literal " + this.value + " but got " + pretty(v)); | ||
}; | ||
return LiteralValidator; | ||
}(Validator)); | ||
function literal(value) { | ||
return new LiteralValidator(value); | ||
return __assign({ validate: function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return v === value | ||
? success(v) | ||
: failure(c, "Expected " + pretty(value) + ", got " + pretty(v)); | ||
} }, validatorMethods); | ||
} | ||
exports.literal = literal; | ||
//-------------------------------------- | ||
// intersection | ||
//-------------------------------------- | ||
var IntersectionValidator = /** @class */ (function (_super) { | ||
__extends(IntersectionValidator, _super); | ||
function IntersectionValidator(validators) { | ||
var _this = _super.call(this) || this; | ||
_this.validators = validators; | ||
return _this; | ||
} | ||
IntersectionValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
var result = {}; | ||
for (var i = 0; i < this.validators.length; i++) { | ||
var validation = this.validators[i].validate(v, config, c); | ||
if (validation.isOk()) { | ||
result = __assign(__assign({}, result), validation.get()); | ||
} | ||
else { | ||
return validation; | ||
} | ||
} | ||
return success(result); | ||
}; | ||
return IntersectionValidator; | ||
}(Validator)); | ||
function intersection() { | ||
var values = []; | ||
var validators = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
values[_i] = arguments[_i]; | ||
validators[_i] = arguments[_i]; | ||
} | ||
return new IntersectionValidator(values); | ||
return __assign({ validate: function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
var result = {}; | ||
for (var i = 0; i < validators.length; i++) { | ||
var validation = validators[i].validate(v, config, c); | ||
if (isOk(validation)) { | ||
result = __assign(__assign({}, result), validation.value); | ||
} | ||
else { | ||
return validation; | ||
} | ||
} | ||
return success(result); | ||
} }, validatorMethods); | ||
} | ||
exports.intersection = intersection; | ||
//-------------------------------------- | ||
// union | ||
//-------------------------------------- | ||
var UnionValidator = /** @class */ (function (_super) { | ||
__extends(UnionValidator, _super); | ||
function UnionValidator(validators) { | ||
var _this = _super.call(this) || this; | ||
_this.validators = validators; | ||
return _this; | ||
} | ||
UnionValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
var errors = []; | ||
for (var i = 0; i < this.validators.length; i++) { | ||
var validation = this.validators[i].validate(v, config, c); | ||
if (validation.isOk()) | ||
return validation; | ||
else | ||
errors.push(validation.get()); | ||
} | ||
var detailString = errors.map(function (es, index) { | ||
return "Union type #" + index + " => \n " + errorDebugString(es).replace(/\n/g, '\n '); | ||
}).join('\n'); | ||
return failure(c, "The value " + pretty(v) + " \nis not part of the union: \n\n" + detailString); | ||
}; | ||
return UnionValidator; | ||
}(Validator)); | ||
exports.UnionValidator = UnionValidator; | ||
var LiteralUnionValidator = /** @class */ (function (_super) { | ||
__extends(LiteralUnionValidator, _super); | ||
function LiteralUnionValidator(values) { | ||
var _this = _super.call(this) || this; | ||
_this.values = values; | ||
return _this; | ||
} | ||
LiteralUnionValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
for (var i = 0; i < this.values.length; i++) { | ||
var validator = literal(this.values[i]); | ||
var validation = validator.validate(v, config, c); | ||
if (validation.isOk()) | ||
return validation; | ||
} | ||
return failure(c, "The value " + pretty(v) + " is not part of the union"); | ||
}; | ||
return LiteralUnionValidator; | ||
}(Validator)); | ||
exports.LiteralUnionValidator = LiteralUnionValidator; | ||
function union() { | ||
var values = []; | ||
var validators = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
values[_i] = arguments[_i]; | ||
validators[_i] = arguments[_i]; | ||
} | ||
var probe = values[0]; | ||
return (probe && typeof probe === 'object') | ||
? new UnionValidator(values) | ||
: new LiteralUnionValidator(values); | ||
var probe = validators[0]; | ||
if (probe && typeof probe === 'object') { | ||
return __assign({ validate: function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
var errors = []; | ||
for (var i = 0; i < validators.length; i++) { | ||
var validation = validators[i].validate(v, config, c); | ||
if (isOk(validation)) | ||
return validation; | ||
else | ||
errors.push(validation.errors); | ||
} | ||
var detailString = errors.map(function (es, index) { | ||
return "Union type #" + index + " => \n " + errorDebugString(es).replace(/\n/g, '\n '); | ||
}).join('\n'); | ||
return failure(c, "The value " + pretty(v) + " \nis not part of the union: \n\n" + detailString); | ||
} }, validatorMethods); | ||
} | ||
return __assign({ validate: function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
for (var i = 0; i < validators.length; i++) { | ||
var validator = literal(validators[i]); | ||
var validation = validator.validate(v, config, c); | ||
if (isOk(validation)) | ||
return validation; | ||
} | ||
return failure(c, "The value " + pretty(v) + " is not part of the union"); | ||
} }, validatorMethods); | ||
} | ||
@@ -502,57 +340,21 @@ exports.union = union; | ||
//-------------------------------------- | ||
var OptionalValidator = /** @class */ (function (_super) { | ||
__extends(OptionalValidator, _super); | ||
function OptionalValidator(validator) { | ||
var _this = _super.call(this) || this; | ||
_this.validator = validator; | ||
return _this; | ||
} | ||
OptionalValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (v === undefined) | ||
return success(v); | ||
return this.validator.validate(v, config, c); | ||
}; | ||
return OptionalValidator; | ||
}(Validator)); | ||
exports.OptionalValidator = OptionalValidator; | ||
function optional(validator) { | ||
return new OptionalValidator(validator); | ||
return __assign({ validate: function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (v === undefined) | ||
return success(v); | ||
return validator.validate(v, config, c); | ||
} }, validatorMethods); | ||
} | ||
exports.optional = optional; | ||
//-------------------------------------- | ||
// option | ||
//-------------------------------------- | ||
var OptionValidator = /** @class */ (function (_super) { | ||
__extends(OptionValidator, _super); | ||
function OptionValidator(validator) { | ||
var _this = _super.call(this) || this; | ||
_this.validator = validator; | ||
return _this; | ||
} | ||
OptionValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (v === undefined || v === null) | ||
return success(space_lift_1.None); | ||
return this.validator.validate(v, config, c).map(space_lift_1.Some); | ||
}; | ||
return OptionValidator; | ||
}(Validator)); | ||
exports.OptionValidator = OptionValidator; | ||
function option(validator) { | ||
return new OptionValidator(validator); | ||
} | ||
exports.option = option; | ||
//-------------------------------------- | ||
// recursion | ||
//-------------------------------------- | ||
function recursion(definition) { | ||
var Self = new Validator(); | ||
Self.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return Result.validate(v, config, c); | ||
}; | ||
var Self = __assign(__assign({}, validatorMethods), { validate: function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return Result.validate(v, config, c); | ||
} }); | ||
var Result = definition(Self); | ||
@@ -563,2 +365,11 @@ return Result; | ||
//-------------------------------------- | ||
// isoDate | ||
//-------------------------------------- | ||
exports.isoDate = exports.string.flatMap(function (str) { | ||
var date = new Date(str); | ||
return isNaN(date.getTime()) | ||
? Err("Expected ISO date, got: " + pretty(str)) | ||
: Ok(date); | ||
}); | ||
//-------------------------------------- | ||
// util | ||
@@ -576,17 +387,1 @@ //-------------------------------------- | ||
exports.errorDebugString = errorDebugString; | ||
//-------------------------------------- | ||
// Export aliases and singletons | ||
//-------------------------------------- | ||
var nullValidator = new NullValidator(); | ||
exports["null"] = nullValidator; | ||
var undefinedValidator = new UndefinedValidator(); | ||
exports.undefined = undefinedValidator; | ||
exports.string = new StringValidator(); | ||
exports.number = new NumberValidator(); | ||
exports.boolean = new BooleanValidator(); | ||
exports.isoDate = exports.string.flatMap(function (str) { | ||
var date = new Date(str); | ||
return isNaN(date.getTime()) | ||
? space_lift_1.Err("Expected an ISO date but got: " + pretty(str)) | ||
: space_lift_1.Ok(date); | ||
}); |
@@ -1,5 +0,4 @@ | ||
import { Result, Ok, Err, Option, None, Some } from 'space-lift'; | ||
export declare abstract class Validator<T> { | ||
export interface Validator<T> { | ||
readonly T: T; | ||
abstract validate(value: Value, config?: Configuration, context?: Context): Validation<T>; | ||
validate(value: Value, config?: Configuration, context?: Context): Validation<T>; | ||
map<B>(fn: (value: T) => B): Validator<B>; | ||
@@ -12,2 +11,20 @@ filter(fn: (value: T) => boolean): Validator<T>; | ||
} | ||
export declare type Ok<VALUE> = { | ||
type: 'ok'; | ||
value: VALUE; | ||
}; | ||
export declare type Err<ERROR> = { | ||
type: 'error'; | ||
errors: ERROR; | ||
}; | ||
export declare type Result<ERROR, VALUE> = Err<ERROR> | Ok<VALUE>; | ||
export declare function Ok<VALUE>(value: VALUE): { | ||
readonly type: "ok"; | ||
readonly value: VALUE; | ||
}; | ||
export declare function Err<ERROR>(errors: ERROR): { | ||
readonly type: "error"; | ||
readonly errors: ERROR; | ||
}; | ||
export declare function isOk<VALUE>(result: Result<unknown, VALUE>): result is Ok<VALUE>; | ||
export declare type Any = Validator<Value>; | ||
@@ -29,41 +46,18 @@ export declare type TypeOf<V extends Any> = V['T']; | ||
export declare function failure(context: Context, message: string): Validation<never>; | ||
export declare function typeFailure(value: any, context: Context, expectedType: string): Result<{ | ||
context: Context; | ||
message: string; | ||
}[], never>; | ||
export declare function typeFailure(value: any, context: Context, expectedType: string): { | ||
readonly type: "error"; | ||
readonly errors: { | ||
context: Context; | ||
message: string; | ||
}[]; | ||
}; | ||
export declare function getContext(name: string, parent?: string): Context; | ||
export declare const snakeCaseTransformation: (key: string) => string; | ||
export declare function is<T>(value: Value, validator: Validator<T>): value is T; | ||
export declare class NullValidator extends Validator<null> { | ||
validate(v: Value, _config?: Configuration, c?: Context): Result<ValidationError[], null>; | ||
} | ||
export declare class UndefinedValidator extends Validator<undefined> { | ||
validate(v: Value, _config?: Configuration, c?: Context): Result<ValidationError[], undefined>; | ||
} | ||
export declare class StringValidator extends Validator<string> { | ||
validate(v: Value, _config?: Configuration, c?: Context): Result<ValidationError[], string>; | ||
} | ||
export declare class NumberValidator extends Validator<number> { | ||
validate(v: Value, _config?: Configuration, c?: Context): Result<ValidationError[], number>; | ||
} | ||
export declare class BooleanValidator extends Validator<boolean> { | ||
validate(v: Value, _config?: Configuration, c?: Context): Result<ValidationError[], boolean>; | ||
} | ||
export declare class TransformValidator<A, B> extends Validator<B> { | ||
private validator; | ||
private f; | ||
constructor(validator: Validator<A>, f: (a: Validation<A>) => Result<string | ValidationError[], B>); | ||
validate(v: Value, config?: Configuration, c?: Context): Result<ValidationError[], B>; | ||
} | ||
export declare class ArrayValidator<A> extends Validator<A[]> { | ||
private validator; | ||
constructor(validator: Validator<A>); | ||
validate(v: Value, config?: Configuration, c?: Context): Ok<ValidationError[], never> | Err<ValidationError[], never> | Ok<never, A[]> | Err<never, A[]>; | ||
} | ||
declare const nullValidator: Validator<null>; | ||
declare const undefinedValidator: Validator<undefined>; | ||
export declare const string: Validator<string>; | ||
export declare const number: Validator<number>; | ||
export declare const boolean: Validator<boolean>; | ||
export declare function array<A>(validator: Validator<A>): Validator<A[]>; | ||
export declare class TupleValidator extends Validator<any> { | ||
private validators; | ||
constructor(validators: Validator<any>[]); | ||
validate(v: Value, config?: Configuration, c?: Context): Ok<ValidationError[], never> | Err<ValidationError[], never> | Ok<never, any[]> | Err<never, any[]>; | ||
} | ||
export declare function tuple<A = never>(): Validator<A[]>; | ||
@@ -97,20 +91,6 @@ export declare function tuple<A>(a: Validator<A>): Validator<[A]>; | ||
}; | ||
export declare class ObjectValidator<P extends Props> extends Validator<ObjectOf<P>> { | ||
export declare function object<P extends Props>(props: P): Validator<ObjectOf<P>> & { | ||
props: P; | ||
constructor(props: P); | ||
validate(v: Value, config?: Configuration, c?: Context): Validation<ObjectOf<P>>; | ||
} | ||
export declare function object<P extends Props>(props: P): ObjectValidator<P>; | ||
export declare class KeyOfValidator<KEYS extends object> extends Validator<keyof KEYS> { | ||
private keys; | ||
constructor(keys: KEYS); | ||
validate(v: Value, _config?: Configuration, c?: Context): Validation<keyof KEYS>; | ||
} | ||
export declare function keyof<KEYS extends object>(keys: KEYS): KeyOfValidator<KEYS>; | ||
export declare class DictionaryValidator<K extends string, V> extends Validator<Record<K, V>> { | ||
private domain; | ||
private codomain; | ||
constructor(domain: Validator<K>, codomain: Validator<V>); | ||
validate(v: Value, config?: Configuration, c?: Context): Ok<ValidationError[], never> | Err<ValidationError[], never> | Ok<never, any> | Err<never, any>; | ||
} | ||
}; | ||
export declare function keyof<KEYS extends object>(keys: KEYS): Validator<keyof KEYS>; | ||
export declare function dictionary<K extends string, V>(domain: Validator<K>, codomain: Validator<V>): Validator<Record<K, V>>; | ||
@@ -125,12 +105,2 @@ export declare type Literal = string | number | boolean | null | undefined; | ||
export declare function intersection<A, B, C, D, E, F>(a: Validator<A>, b: Validator<B>, c: Validator<C>, d: Validator<D>, e: Validator<E>, f: Validator<F>): Validator<A & B & C & D & E & F>; | ||
export declare class UnionValidator<A> extends Validator<A> { | ||
private validators; | ||
constructor(validators: Validator<A>[]); | ||
validate(v: Value, config?: Configuration, c?: Context): Err<ValidationError[], never> | Ok<ValidationError[], A>; | ||
} | ||
export declare class LiteralUnionValidator<A extends Literal> extends Validator<A> { | ||
private values; | ||
constructor(values: A[]); | ||
validate(v: Value, config?: Configuration, c?: Context): Err<ValidationError[], never> | Ok<ValidationError[], A>; | ||
} | ||
export declare function union<A, B>(a: Validator<A>, b: Validator<B>): Validator<A | B>; | ||
@@ -154,22 +124,6 @@ export declare function union<A extends Literal, B extends Literal>(a: A, b: B): Validator<A | B>; | ||
export declare function union<A extends Literal, B extends Literal, C extends Literal, D extends Literal, E extends Literal, F extends Literal, G extends Literal, H extends Literal, I extends Literal, J extends Literal>(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J): Validator<A | B | C | D | E | F | G | H | I | J>; | ||
export declare class OptionalValidator<V> extends Validator<V | undefined> { | ||
private validator; | ||
constructor(validator: Validator<V>); | ||
validate(v: Value, config?: Configuration, c?: Context): Ok<ValidationError[], undefined> | Err<ValidationError[], undefined> | Ok<ValidationError[], V> | Err<ValidationError[], V>; | ||
} | ||
export declare function optional<V>(validator: Validator<V>): Validator<V | undefined>; | ||
export declare class OptionValidator<V> extends Validator<Option<V>> { | ||
private validator; | ||
constructor(validator: Validator<V>); | ||
validate(v: Value, config?: Configuration, c?: Context): Ok<ValidationError[], None> | Err<ValidationError[], None> | Ok<ValidationError[], Some<V>> | Err<ValidationError[], Some<V>>; | ||
} | ||
export declare function option<V>(validator: Validator<V>): Validator<Option<V>>; | ||
export declare function recursion<T>(definition: (self: Validator<T>) => Any): Validator<T>; | ||
export declare const isoDate: Validator<Date>; | ||
export declare function errorDebugString(errors: ValidationError[]): string; | ||
declare const nullValidator: NullValidator; | ||
declare const undefinedValidator: UndefinedValidator; | ||
export { nullValidator as null, undefinedValidator as undefined }; | ||
export declare const string: StringValidator; | ||
export declare const number: NumberValidator; | ||
export declare const boolean: BooleanValidator; | ||
export declare const isoDate: Validator<Date>; |
@@ -1,51 +0,42 @@ | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
import { Ok, Err, None, Some } from 'space-lift'; | ||
//-------------------------------------- | ||
// Setup | ||
//-------------------------------------- | ||
var Validator = /** @class */ (function () { | ||
function Validator() { | ||
this.T = null; // Phantom type | ||
const validatorMethods = { | ||
map(fn) { | ||
return this.flatMap(v => Ok(fn(v))); | ||
}, | ||
filter(fn) { | ||
return this.flatMap(v => fn(v) ? Ok(v) : Err(`filter error: ${pretty(v)}"`)); | ||
}, | ||
flatMap(fn) { | ||
return this.transform(r => isOk(r) ? fn(r.value) : r); | ||
}, | ||
transform(fn) { | ||
const validator = this; | ||
return Object.assign({}, validatorMethods, { | ||
validate(v, config = defaultConfig, c = rootContext) { | ||
const validated = validator.validate(v, config, c); | ||
const transformed = fn(validated); | ||
if (isOk(transformed)) | ||
return success(transformed.value); | ||
const error = transformed.errors; | ||
if (typeof error === 'string') | ||
return failure(c, error); | ||
return Err(error); | ||
} | ||
}); | ||
}, | ||
tagged() { | ||
return this; | ||
} | ||
Validator.prototype.map = function (fn) { | ||
return this.flatMap(function (v) { return Ok(fn(v)); }); | ||
}; | ||
Validator.prototype.filter = function (fn) { | ||
return this.flatMap(function (v) { return fn(v) ? Ok(v) : Err("The value " + pretty(v) + " failed a predicate\""); }); | ||
}; | ||
Validator.prototype.flatMap = function (fn) { | ||
return this.transform(function (r) { return r.isOk() ? fn(r.get()) : r; }); | ||
}; | ||
Validator.prototype.transform = function (fn) { | ||
return new TransformValidator(this, fn); | ||
}; | ||
Validator.prototype.tagged = function () { | ||
return this; | ||
}; | ||
return Validator; | ||
}()); | ||
export { Validator }; | ||
}; | ||
export function Ok(value) { | ||
return { type: 'ok', value }; | ||
} | ||
export function Err(errors) { | ||
return { type: 'error', errors }; | ||
} | ||
export function isOk(result) { | ||
return result.type === 'ok'; | ||
} | ||
export function success(value) { | ||
@@ -55,6 +46,6 @@ return Ok(value); | ||
export function failure(context, message) { | ||
return Err([{ context: context, message: message }]); | ||
return Err([{ context, message }]); | ||
} | ||
export function typeFailure(value, context, expectedType) { | ||
var valueType = (function () { | ||
const valueType = (() => { | ||
if (Array.isArray(value)) | ||
@@ -66,20 +57,18 @@ return 'array'; | ||
})(); | ||
var message = "Type error: expected " + expectedType + " but got " + valueType; | ||
return Err([{ context: context, message: message }]); | ||
const message = `Expected ${expectedType}, got ${valueType}`; | ||
return Err([{ context, message }]); | ||
} | ||
export function getContext(name, parent) { | ||
return (parent ? parent + " / " + name : name); | ||
return (parent ? `${parent} / ${name}` : name); | ||
} | ||
var rootContext = getContext('root'); | ||
var defaultConfig = {}; | ||
var upperThenLower = /([A-Z]+)([A-Z][a-z])/g; | ||
var lowerThenUpper = /([a-z\\\\d])([A-Z])/g; | ||
export var snakeCaseTransformation = function (key) { | ||
return key | ||
.replace(upperThenLower, '$1_$2') | ||
.replace(lowerThenUpper, '$1_$2') | ||
.toLowerCase(); | ||
}; | ||
const rootContext = getContext('root'); | ||
const defaultConfig = {}; | ||
const upperThenLower = /([A-Z]+)([A-Z][a-z])/g; | ||
const lowerThenUpper = /([a-z\\\\d])([A-Z])/g; | ||
export const snakeCaseTransformation = (key) => key | ||
.replace(upperThenLower, '$1_$2') | ||
.replace(lowerThenUpper, '$1_$2') | ||
.toLowerCase(); | ||
export function is(value, validator) { | ||
return validator.validate(value).isOk(); | ||
return isOk(validator.validate(value)); | ||
} | ||
@@ -89,205 +78,73 @@ //-------------------------------------- | ||
//-------------------------------------- | ||
var NullValidator = /** @class */ (function (_super) { | ||
__extends(NullValidator, _super); | ||
function NullValidator() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
NullValidator.prototype.validate = function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return v === null ? success(v) : typeFailure(v, c, 'null'); | ||
}; | ||
return NullValidator; | ||
}(Validator)); | ||
export { NullValidator }; | ||
var UndefinedValidator = /** @class */ (function (_super) { | ||
__extends(UndefinedValidator, _super); | ||
function UndefinedValidator() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
UndefinedValidator.prototype.validate = function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return v === void 0 ? success(v) : typeFailure(v, c, 'undefined'); | ||
}; | ||
return UndefinedValidator; | ||
}(Validator)); | ||
export { UndefinedValidator }; | ||
var StringValidator = /** @class */ (function (_super) { | ||
__extends(StringValidator, _super); | ||
function StringValidator() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
StringValidator.prototype.validate = function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return typeof v === 'string' ? success(v) : typeFailure(v, c, 'string'); | ||
}; | ||
return StringValidator; | ||
}(Validator)); | ||
export { StringValidator }; | ||
var NumberValidator = /** @class */ (function (_super) { | ||
__extends(NumberValidator, _super); | ||
function NumberValidator() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
NumberValidator.prototype.validate = function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return typeof v === 'number' ? success(v) : typeFailure(v, c, 'number'); | ||
}; | ||
return NumberValidator; | ||
}(Validator)); | ||
export { NumberValidator }; | ||
var BooleanValidator = /** @class */ (function (_super) { | ||
__extends(BooleanValidator, _super); | ||
function BooleanValidator() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
} | ||
BooleanValidator.prototype.validate = function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return typeof v === 'boolean' ? success(v) : typeFailure(v, c, 'boolean'); | ||
}; | ||
return BooleanValidator; | ||
}(Validator)); | ||
export { BooleanValidator }; | ||
const nullValidator = Object.assign({ validate: (v, _config = defaultConfig, c = rootContext) => v === null ? success(v) : typeFailure(v, c, 'null') }, validatorMethods); | ||
const undefinedValidator = Object.assign({ validate: (v, _config = defaultConfig, c = rootContext) => v === void 0 ? success(v) : typeFailure(v, c, 'undefined') }, validatorMethods); | ||
export const string = Object.assign({ validate: (v, _config = defaultConfig, c = rootContext) => typeof v === 'string' ? success(v) : typeFailure(v, c, 'string') }, validatorMethods); | ||
export const number = Object.assign({ validate: (v, _config = defaultConfig, c = rootContext) => typeof v === 'number' ? success(v) : typeFailure(v, c, 'number') }, validatorMethods); | ||
export const boolean = Object.assign({ validate: (v, _config = defaultConfig, c = rootContext) => typeof v === 'boolean' ? success(v) : typeFailure(v, c, 'boolean') }, validatorMethods); | ||
//-------------------------------------- | ||
// transform | ||
//-------------------------------------- | ||
var TransformValidator = /** @class */ (function (_super) { | ||
__extends(TransformValidator, _super); | ||
function TransformValidator(validator, f) { | ||
var _this = _super.call(this) || this; | ||
_this.validator = validator; | ||
_this.f = f; | ||
return _this; | ||
} | ||
TransformValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
var validated = this.validator.validate(v, config, c); | ||
var transformed = this.f(validated); | ||
if (transformed.isOk()) | ||
return success(transformed.get()); | ||
var error = transformed.get(); | ||
if (typeof error === 'string') | ||
return failure(c, error); | ||
return Err(error); | ||
}; | ||
return TransformValidator; | ||
}(Validator)); | ||
export { TransformValidator }; | ||
//-------------------------------------- | ||
// array | ||
//-------------------------------------- | ||
var ArrayValidator = /** @class */ (function (_super) { | ||
__extends(ArrayValidator, _super); | ||
function ArrayValidator(validator) { | ||
var _this = _super.call(this) || this; | ||
_this.validator = validator; | ||
return _this; | ||
} | ||
ArrayValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (!Array.isArray(v)) | ||
return typeFailure(v, c, 'array'); | ||
var validatedArray = []; | ||
var errors = []; | ||
for (var i = 0; i < v.length; i++) { | ||
var item = v[i]; | ||
var validation = this.validator.validate(item, config, getContext(String(i), c)); | ||
if (validation.isOk()) { | ||
validatedArray.push(validation.get()); | ||
export function array(validator) { | ||
return Object.assign({ validate(v, config = defaultConfig, c = rootContext) { | ||
if (!Array.isArray(v)) | ||
return typeFailure(v, c, 'array'); | ||
const validatedArray = []; | ||
const errors = []; | ||
for (let i = 0; i < v.length; i++) { | ||
const item = v[i]; | ||
const validation = validator.validate(item, config, getContext(String(i), c)); | ||
if (isOk(validation)) { | ||
validatedArray.push(validation.value); | ||
} | ||
else { | ||
pushAll(errors, validation.errors); | ||
} | ||
} | ||
else { | ||
pushAll(errors, validation.get()); | ||
} | ||
} | ||
return errors.length ? Err(errors) : Ok(validatedArray); | ||
}; | ||
return ArrayValidator; | ||
}(Validator)); | ||
export { ArrayValidator }; | ||
export function array(validator) { | ||
return new ArrayValidator(validator); | ||
return errors.length ? Err(errors) : Ok(validatedArray); | ||
} }, validatorMethods); | ||
} | ||
//-------------------------------------- | ||
// tuple | ||
//-------------------------------------- | ||
var TupleValidator = /** @class */ (function (_super) { | ||
__extends(TupleValidator, _super); | ||
function TupleValidator(validators) { | ||
var _this = _super.call(this) || this; | ||
_this.validators = validators; | ||
return _this; | ||
} | ||
TupleValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (!Array.isArray(v)) | ||
return typeFailure(v, c, 'Tuple'); | ||
if (v.length !== this.validators.length) | ||
return failure(c, "Expected Tuple" + this.validators.length + ", got Tuple" + v.length); | ||
var validatedArray = []; | ||
var errors = []; | ||
for (var i = 0; i < v.length; i++) { | ||
var item = v[i]; | ||
var validation = this.validators[i].validate(item, config, getContext(String(i), c)); | ||
if (validation.isOk()) { | ||
validatedArray.push(validation.get()); | ||
export function tuple(...validators) { | ||
return Object.assign({ validate(v, config = defaultConfig, c = rootContext) { | ||
if (!Array.isArray(v)) | ||
return typeFailure(v, c, 'Tuple'); | ||
if (v.length !== validators.length) | ||
return failure(c, `Expected Tuple${validators.length}, got Tuple${v.length}`); | ||
const validatedArray = []; | ||
const errors = []; | ||
for (let i = 0; i < v.length; i++) { | ||
const item = v[i]; | ||
const validation = validators[i].validate(item, config, getContext(String(i), c)); | ||
if (isOk(validation)) { | ||
validatedArray.push(validation.value); | ||
} | ||
else { | ||
pushAll(errors, validation.errors); | ||
} | ||
} | ||
else { | ||
pushAll(errors, validation.get()); | ||
} | ||
} | ||
return errors.length ? Err(errors) : Ok(validatedArray); | ||
}; | ||
return TupleValidator; | ||
}(Validator)); | ||
export { TupleValidator }; | ||
export function tuple() { | ||
var validators = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
validators[_i] = arguments[_i]; | ||
} | ||
return new TupleValidator(validators); | ||
return errors.length ? Err(errors) : Ok(validatedArray); | ||
} }, validatorMethods); | ||
} | ||
var ObjectValidator = /** @class */ (function (_super) { | ||
__extends(ObjectValidator, _super); | ||
function ObjectValidator(props) { | ||
var _this = _super.call(this) || this; | ||
_this.props = props; | ||
return _this; | ||
} | ||
ObjectValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (v == null || typeof v !== 'object') | ||
return typeFailure(v, c, 'object'); | ||
var validatedObject = {}; | ||
var errors = []; | ||
for (var key in this.props) { | ||
var transformedKey = config.transformObjectKeys !== undefined | ||
? config.transformObjectKeys(key) | ||
: key; | ||
var value = v[transformedKey]; | ||
var validator = this.props[key]; | ||
var validation = validator.validate(value, config, getContext(transformedKey, c)); | ||
if (validation.isOk()) { | ||
if (validation.get() !== undefined) | ||
validatedObject[key] = validation.get(); | ||
export function object(props) { | ||
return Object.assign({ props, validate(v, config = defaultConfig, c = rootContext) { | ||
if (v == null || typeof v !== 'object') | ||
return typeFailure(v, c, 'object'); | ||
const validatedObject = {}; | ||
const errors = []; | ||
for (let key in props) { | ||
const transformedKey = config.transformObjectKeys !== undefined | ||
? config.transformObjectKeys(key) | ||
: key; | ||
const value = v[transformedKey]; | ||
const validator = props[key]; | ||
const validation = validator.validate(value, config, getContext(transformedKey, c)); | ||
if (isOk(validation)) { | ||
if (validation.value !== undefined) | ||
validatedObject[key] = validation.value; | ||
} | ||
else { | ||
pushAll(errors, validation.errors); | ||
} | ||
} | ||
else { | ||
pushAll(errors, validation.get()); | ||
} | ||
} | ||
return errors.length ? Err(errors) : Ok(validatedObject); | ||
}; | ||
return ObjectValidator; | ||
}(Validator)); | ||
export { ObjectValidator }; | ||
export function object(props) { | ||
return new ObjectValidator(props); | ||
return errors.length ? Err(errors) : Ok(validatedObject); | ||
} }, validatorMethods); | ||
} | ||
@@ -297,21 +154,8 @@ //-------------------------------------- | ||
//-------------------------------------- | ||
var KeyOfValidator = /** @class */ (function (_super) { | ||
__extends(KeyOfValidator, _super); | ||
function KeyOfValidator(keys) { | ||
var _this = _super.call(this) || this; | ||
_this.keys = keys; | ||
return _this; | ||
} | ||
KeyOfValidator.prototype.validate = function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return this.keys.hasOwnProperty(v) | ||
? success(v) | ||
: failure(c, pretty(v) + " is not a key of " + pretty(this.keys)); | ||
}; | ||
return KeyOfValidator; | ||
}(Validator)); | ||
export { KeyOfValidator }; | ||
export function keyof(keys) { | ||
return new KeyOfValidator(keys); | ||
return Object.assign({ validate(v, _config = defaultConfig, c = rootContext) { | ||
return keys.hasOwnProperty(v) | ||
? success(v) | ||
: failure(c, `${pretty(v)} is not a key of ${pretty(keys)}`); | ||
} }, validatorMethods); | ||
} | ||
@@ -321,161 +165,78 @@ //-------------------------------------- | ||
//-------------------------------------- | ||
var DictionaryValidator = /** @class */ (function (_super) { | ||
__extends(DictionaryValidator, _super); | ||
function DictionaryValidator(domain, codomain) { | ||
var _this = _super.call(this) || this; | ||
_this.domain = domain; | ||
_this.codomain = codomain; | ||
return _this; | ||
} | ||
DictionaryValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (v == null || typeof v !== 'object') | ||
return typeFailure(v, c, 'object'); | ||
var validatedDict = {}; | ||
var errors = []; | ||
var _loop_1 = function (key) { | ||
var value = v[key]; | ||
var context = getContext(key, c); | ||
var domainValidation = this_1.domain.validate(key, config, context); | ||
var codomainValidation = this_1.codomain.validate(value, config, context); | ||
if (domainValidation.isOk()) { | ||
key = domainValidation.get(); | ||
export function dictionary(domain, codomain) { | ||
return Object.assign({ validate(v, config = defaultConfig, c = rootContext) { | ||
if (v == null || typeof v !== 'object') | ||
return typeFailure(v, c, 'object'); | ||
const validatedDict = {}; | ||
const errors = []; | ||
for (let key in v) { | ||
const value = v[key]; | ||
const context = getContext(key, c); | ||
const domainValidation = domain.validate(key, config, context); | ||
const codomainValidation = codomain.validate(value, config, context); | ||
if (isOk(domainValidation)) { | ||
key = domainValidation.value; | ||
} | ||
else { | ||
const error = domainValidation.errors; | ||
pushAll(errors, error.map(e => ({ context, message: `key error: ${e.message}` }))); | ||
} | ||
if (isOk(codomainValidation)) { | ||
validatedDict[key] = codomainValidation.value; | ||
} | ||
else { | ||
const error = codomainValidation.errors; | ||
pushAll(errors, error.map(e => ({ context, message: `value error: ${e.message}` }))); | ||
} | ||
} | ||
else { | ||
var error = domainValidation.get(); | ||
pushAll(errors, error.map(function (e) { return ({ context: context, message: "key error: " + e.message }); })); | ||
} | ||
if (codomainValidation.isOk()) { | ||
validatedDict[key] = codomainValidation.get(); | ||
} | ||
else { | ||
var error = codomainValidation.get(); | ||
pushAll(errors, error.map(function (e) { return ({ context: context, message: "value error: " + e.message }); })); | ||
} | ||
}; | ||
var this_1 = this; | ||
for (var key in v) { | ||
_loop_1(key); | ||
} | ||
return errors.length ? Err(errors) : Ok(validatedDict); | ||
}; | ||
return DictionaryValidator; | ||
}(Validator)); | ||
export { DictionaryValidator }; | ||
export function dictionary(domain, codomain) { | ||
return new DictionaryValidator(domain, codomain); | ||
return errors.length ? Err(errors) : Ok(validatedDict); | ||
} }, validatorMethods); | ||
} | ||
var LiteralValidator = /** @class */ (function (_super) { | ||
__extends(LiteralValidator, _super); | ||
function LiteralValidator(value) { | ||
var _this = _super.call(this) || this; | ||
_this.value = value; | ||
return _this; | ||
} | ||
LiteralValidator.prototype.validate = function (v, _config, c) { | ||
if (_config === void 0) { _config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return v === this.value | ||
? success(v) | ||
: failure(c, "Expected literal " + this.value + " but got " + pretty(v)); | ||
}; | ||
return LiteralValidator; | ||
}(Validator)); | ||
export function literal(value) { | ||
return new LiteralValidator(value); | ||
return Object.assign({ validate(v, _config = defaultConfig, c = rootContext) { | ||
return v === value | ||
? success(v) | ||
: failure(c, `Expected ${pretty(value)}, got ${pretty(v)}`); | ||
} }, validatorMethods); | ||
} | ||
//-------------------------------------- | ||
// intersection | ||
//-------------------------------------- | ||
var IntersectionValidator = /** @class */ (function (_super) { | ||
__extends(IntersectionValidator, _super); | ||
function IntersectionValidator(validators) { | ||
var _this = _super.call(this) || this; | ||
_this.validators = validators; | ||
return _this; | ||
} | ||
IntersectionValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
var result = {}; | ||
for (var i = 0; i < this.validators.length; i++) { | ||
var validation = this.validators[i].validate(v, config, c); | ||
if (validation.isOk()) { | ||
result = __assign(__assign({}, result), validation.get()); | ||
export function intersection(...validators) { | ||
return Object.assign({ validate(v, config = defaultConfig, c = rootContext) { | ||
let result = {}; | ||
for (let i = 0; i < validators.length; i++) { | ||
const validation = validators[i].validate(v, config, c); | ||
if (isOk(validation)) { | ||
result = Object.assign(Object.assign({}, result), validation.value); | ||
} | ||
else { | ||
return validation; | ||
} | ||
} | ||
else { | ||
return validation; | ||
} | ||
} | ||
return success(result); | ||
}; | ||
return IntersectionValidator; | ||
}(Validator)); | ||
export function intersection() { | ||
var values = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
values[_i] = arguments[_i]; | ||
} | ||
return new IntersectionValidator(values); | ||
return success(result); | ||
} }, validatorMethods); | ||
} | ||
//-------------------------------------- | ||
// union | ||
//-------------------------------------- | ||
var UnionValidator = /** @class */ (function (_super) { | ||
__extends(UnionValidator, _super); | ||
function UnionValidator(validators) { | ||
var _this = _super.call(this) || this; | ||
_this.validators = validators; | ||
return _this; | ||
export function union(...validators) { | ||
const probe = validators[0]; | ||
if (probe && typeof probe === 'object') { | ||
return Object.assign({ validate(v, config = defaultConfig, c = rootContext) { | ||
const errors = []; | ||
for (let i = 0; i < validators.length; i++) { | ||
const validation = validators[i].validate(v, config, c); | ||
if (isOk(validation)) | ||
return validation; | ||
else | ||
errors.push(validation.errors); | ||
} | ||
const detailString = errors.map((es, index) => `Union type #${index} => \n ${errorDebugString(es).replace(/\n/g, '\n ')}`).join('\n'); | ||
return failure(c, `The value ${pretty(v)} \nis not part of the union: \n\n${detailString}`); | ||
} }, validatorMethods); | ||
} | ||
UnionValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
var errors = []; | ||
for (var i = 0; i < this.validators.length; i++) { | ||
var validation = this.validators[i].validate(v, config, c); | ||
if (validation.isOk()) | ||
return validation; | ||
else | ||
errors.push(validation.get()); | ||
} | ||
var detailString = errors.map(function (es, index) { | ||
return "Union type #" + index + " => \n " + errorDebugString(es).replace(/\n/g, '\n '); | ||
}).join('\n'); | ||
return failure(c, "The value " + pretty(v) + " \nis not part of the union: \n\n" + detailString); | ||
}; | ||
return UnionValidator; | ||
}(Validator)); | ||
export { UnionValidator }; | ||
var LiteralUnionValidator = /** @class */ (function (_super) { | ||
__extends(LiteralUnionValidator, _super); | ||
function LiteralUnionValidator(values) { | ||
var _this = _super.call(this) || this; | ||
_this.values = values; | ||
return _this; | ||
} | ||
LiteralUnionValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
for (var i = 0; i < this.values.length; i++) { | ||
var validator = literal(this.values[i]); | ||
var validation = validator.validate(v, config, c); | ||
if (validation.isOk()) | ||
return validation; | ||
} | ||
return failure(c, "The value " + pretty(v) + " is not part of the union"); | ||
}; | ||
return LiteralUnionValidator; | ||
}(Validator)); | ||
export { LiteralUnionValidator }; | ||
export function union() { | ||
var values = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
values[_i] = arguments[_i]; | ||
} | ||
var probe = values[0]; | ||
return (probe && typeof probe === 'object') | ||
? new UnionValidator(values) | ||
: new LiteralUnionValidator(values); | ||
return Object.assign({ validate(v, config = defaultConfig, c = rootContext) { | ||
for (let i = 0; i < validators.length; i++) { | ||
const validator = literal(validators[i]); | ||
const validation = validator.validate(v, config, c); | ||
if (isOk(validation)) | ||
return validation; | ||
} | ||
return failure(c, `The value ${pretty(v)} is not part of the union`); | ||
} }, validatorMethods); | ||
} | ||
@@ -485,59 +246,27 @@ //-------------------------------------- | ||
//-------------------------------------- | ||
var OptionalValidator = /** @class */ (function (_super) { | ||
__extends(OptionalValidator, _super); | ||
function OptionalValidator(validator) { | ||
var _this = _super.call(this) || this; | ||
_this.validator = validator; | ||
return _this; | ||
} | ||
OptionalValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (v === undefined) | ||
return success(v); | ||
return this.validator.validate(v, config, c); | ||
}; | ||
return OptionalValidator; | ||
}(Validator)); | ||
export { OptionalValidator }; | ||
export function optional(validator) { | ||
return new OptionalValidator(validator); | ||
return Object.assign({ validate(v, config = defaultConfig, c = rootContext) { | ||
if (v === undefined) | ||
return success(v); | ||
return validator.validate(v, config, c); | ||
} }, validatorMethods); | ||
} | ||
//-------------------------------------- | ||
// option | ||
//-------------------------------------- | ||
var OptionValidator = /** @class */ (function (_super) { | ||
__extends(OptionValidator, _super); | ||
function OptionValidator(validator) { | ||
var _this = _super.call(this) || this; | ||
_this.validator = validator; | ||
return _this; | ||
} | ||
OptionValidator.prototype.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
if (v === undefined || v === null) | ||
return success(None); | ||
return this.validator.validate(v, config, c).map(Some); | ||
}; | ||
return OptionValidator; | ||
}(Validator)); | ||
export { OptionValidator }; | ||
export function option(validator) { | ||
return new OptionValidator(validator); | ||
} | ||
//-------------------------------------- | ||
// recursion | ||
//-------------------------------------- | ||
export function recursion(definition) { | ||
var Self = new Validator(); | ||
Self.validate = function (v, config, c) { | ||
if (config === void 0) { config = defaultConfig; } | ||
if (c === void 0) { c = rootContext; } | ||
return Result.validate(v, config, c); | ||
}; | ||
var Result = definition(Self); | ||
const Self = Object.assign(Object.assign({}, validatorMethods), { validate: (v, config = defaultConfig, c = rootContext) => Result.validate(v, config, c) }); | ||
const Result = definition(Self); | ||
return Result; | ||
} | ||
//-------------------------------------- | ||
// isoDate | ||
//-------------------------------------- | ||
export const isoDate = string.flatMap(str => { | ||
const date = new Date(str); | ||
return isNaN(date.getTime()) | ||
? Err(`Expected ISO date, got: ${pretty(str)}`) | ||
: Ok(date); | ||
}); | ||
//-------------------------------------- | ||
// util | ||
@@ -552,18 +281,7 @@ //-------------------------------------- | ||
export function errorDebugString(errors) { | ||
return errors.map(function (e) { return "At [" + e.context + "] " + e.message; }).join('\n'); | ||
return errors.map(e => `At [${e.context}] ${e.message}`).join('\n'); | ||
} | ||
//-------------------------------------- | ||
// Export aliases and singletons | ||
// Export aliases | ||
//-------------------------------------- | ||
var nullValidator = new NullValidator(); | ||
var undefinedValidator = new UndefinedValidator(); | ||
export { nullValidator as null, undefinedValidator as undefined }; | ||
export var string = new StringValidator(); | ||
export var number = new NumberValidator(); | ||
export var boolean = new BooleanValidator(); | ||
export var isoDate = string.flatMap(function (str) { | ||
var date = new Date(str); | ||
return isNaN(date.getTime()) | ||
? Err("Expected an ISO date but got: " + pretty(str)) | ||
: Ok(date); | ||
}); |
{ | ||
"name": "validation.ts", | ||
"version": "0.0.27", | ||
"version": "0.0.28", | ||
"description": "Validation for TypeScript", | ||
@@ -10,6 +10,2 @@ "license": "MIT", | ||
"dependencies": { | ||
"space-lift": ">=0.0.0" | ||
}, | ||
"devDependencies": { | ||
@@ -20,3 +16,3 @@ "chalk": "1.1.1", | ||
"mocha": "2.2.5", | ||
"typescript": "3.7.4" | ||
"typescript": "4.0.2" | ||
}, | ||
@@ -26,4 +22,4 @@ | ||
"build": "npm run build-es && npm run build-commonjs", | ||
"build-es": "tsc validation.ts --outDir es --strict --noUnusedParameters --declaration --lib dom,es5,es6 --module es6 --moduleResolution node", | ||
"build-commonjs": "tsc validation.ts --outDir commonjs --strict --noUnusedParameters --declaration --lib dom,es5,es6", | ||
"build-es": "tsc validation.ts --outDir es --strict --noUnusedParameters --declaration --lib dom,es5,es6 --module es6 --target es6 --moduleResolution node", | ||
"build-commonjs": "tsc validation.ts --outDir commonjs --strict --noUnusedParameters --declaration --lib dom,es5,es6 --target es5", | ||
"pretest": "npm run build && tsc test/mocha.d.ts test/global.d.ts test/expect.d.ts test/test.ts --strict", | ||
@@ -30,0 +26,0 @@ "test": "mocha --recursive && node test/testCompilationErrors.js", |
@@ -9,3 +9,3 @@ # validation.ts | ||
Every validator has a `validate` function which returns a [Result](https://github.com/AlexGalays/spacelift#api.result) | ||
Every validator has a `validate` function which returns a Result (either a {type: 'ok', value} or a {type: 'error', errors}) | ||
@@ -16,3 +16,3 @@ A validated value can be transformed at any point during the validation process (e.g. `isoDate`). | ||
```ts | ||
import { errorDebugString } from 'validation.ts' | ||
import { errorDebugString, isOk } from 'validation.ts' | ||
@@ -23,6 +23,8 @@ const myValidator = ... | ||
result.fold( | ||
errors => console.error(errorDebugString(errors)), | ||
validatedJson => console.log(validatedJson) | ||
) | ||
if (isOk(result)) { | ||
console.log(result.value) | ||
} | ||
else { | ||
console.error(errorDebugString(result.errors)) | ||
} | ||
``` | ||
@@ -109,8 +111,2 @@ | ||
## option | ||
Whereas `optional` returns an `T | undefined`, `option` return an `Option<T>` | ||
## dictionary | ||
@@ -172,2 +168,5 @@ | ||
Instead of using the derived type as your sole interface, use it to compare its compatibility with your | ||
handcrafted interfaces which will always be more readable in IDE's tooltips. | ||
```ts | ||
@@ -181,4 +180,4 @@ import { object, string, number } from 'validation.ts' | ||
type Person = typeof person.T | ||
/* | ||
type PersonFromValidator = typeof person.T | ||
type Person = { | ||
@@ -188,3 +187,2 @@ name: string | ||
} | ||
*/ | ||
``` | ||
@@ -191,0 +189,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Floating dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 1 instance in 1 package
0
1
53842
910
208
1
- Removedspace-lift@>=0.0.0
- Removedspace-lift@1.0.4(transitive)