@thisisagile/easy
Version: 
Straightforward library for building domain-driven microservice architectures
62 lines (45 loc) • 2.1 kB
text/typescript
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<W> {
  constructor(
    readonly subject: W,
    readonly valid = true,
    private results?: Results
  ) {}
  get not(): When<W> {
    return this.clone(!this.valid);
  }
  get and(): When<W> {
    return this.clone(this.valid);
  }
  get isDefined(): When<W> {
    return this.clone(this.valid === isDefined(this.subject));
  }
  get isEmpty(): When<W> {
    return this.clone(this.valid === isEmpty(this.subject));
  }
  get isTrue(): When<W> {
    return this.clone(this.valid === !!this.subject);
  }
  get isValid(): When<W> {
    this.results = validate(this.subject);
    return this.clone(this.valid === this.results.isValid);
  }
  isInstance = <U>(c: Constructor<U>): When<W> => this.clone(this.valid === this.subject instanceof c);
  with = (pred: Predicate<W>): When<W> => this.clone(this.valid === ofGet(pred, this.subject));
  contains = (property: (w: W) => unknown): When<W> => this.clone(this.valid === isDefined(ofGet(property, this.subject)));
  in = (...items: W[]): When<W> => this.clone(this.valid === isIn(this.subject, toArray(...items)));
  is = (item: W): When<W> => this.clone(this.valid === (this.subject === item));
  reject = (error?: Get<ErrorOrigin, W>): Promise<NonNullable<W>> =>
    !this.valid ? resolve(this.subject as NonNullable<W>) : reject(ofGet(error, this.subject) ?? this.results ?? Exception.Unknown);
  recover = (f: (item: W) => W | Promise<W>): Promise<W> => resolve(!this.valid ? this.subject : f(this.subject));
  protected clone = (result = true): When<W> => new When(this.subject, result, this.results);
}
export const when = <T>(subject: T): When<T> => new When<T>(subject);