import { validate } from './Validate'; import { Results } from '../types/Results'; import { Constructor } from '../types/Constructor'; import { Get, ofGet, Predicate } from '../types/Get'; import { isDefined, isEmpty, isIn } from '../types/Is'; import { toArray } from '../types/Array'; import { ErrorOrigin } from '../types/ErrorOrigin'; import { reject, resolve } from '../utils/Promise'; import { Exception } from '../types/Exception'; export class When { constructor( readonly subject: W, readonly valid = true, private results?: Results ) {} get not(): When { return this.clone(!this.valid); } get and(): When { return this.clone(this.valid); } get isDefined(): When { return this.clone(this.valid === isDefined(this.subject)); } get isEmpty(): When { return this.clone(this.valid === isEmpty(this.subject)); } get isTrue(): When { return this.clone(this.valid === !!this.subject); } get isValid(): When { this.results = validate(this.subject); return this.clone(this.valid === this.results.isValid); } isInstance = (c: Constructor): When => this.clone(this.valid === this.subject instanceof c); with = (pred: Predicate): When => this.clone(this.valid === ofGet(pred, this.subject)); contains = (property: (w: W) => unknown): When => this.clone(this.valid === isDefined(ofGet(property, this.subject))); in = (...items: W[]): When => this.clone(this.valid === isIn(this.subject, toArray(...items))); is = (item: W): When => this.clone(this.valid === (this.subject === item)); reject = (error?: Get): Promise> => !this.valid ? resolve(this.subject as NonNullable) : reject(ofGet(error, this.subject) ?? this.results ?? Exception.Unknown); recover = (f: (item: W) => W | Promise): Promise => resolve(!this.valid ? this.subject : f(this.subject)); protected clone = (result = true): When => new When(this.subject, result, this.results); } export const when = (subject: T): When => new When(subject);