UNPKG

@thisisagile/easy

Version:

Straightforward library for building domain-driven microservice architectures

315 lines (310 loc) • 8.68 kB
import { isValidatable } from "./chunk-OFGI5FLG.mjs"; import { isResults, toResults } from "./chunk-NCEWAKOZ.mjs"; import { toResult } from "./chunk-Q3WMGUO2.mjs"; import { reject, resolve } from "./chunk-5HENJTR6.mjs"; import { Exception } from "./chunk-FKZ4MOTX.mjs"; import { isValue } from "./chunk-WSBULPUZ.mjs"; import { isEnum } from "./chunk-JVDKV5HE.mjs"; import { meta } from "./chunk-WTFW6DLP.mjs"; import { text } from "./chunk-MCCIBDEH.mjs"; import { toList } from "./chunk-A7C3XND3.mjs"; import { toArray } from "./chunk-CO2AFYVD.mjs"; import { asString } from "./chunk-BDA5LB4S.mjs"; import { ofGet } from "./chunk-SJGQU3OG.mjs"; import { ofConstruct, toName } from "./chunk-ZPNFXK7Y.mjs"; import { isArray, isDefined, isEmpty, isFunction, isIn, isTrue } from "./chunk-DEJ7A5PY.mjs"; // src/types/Try.ts var Try = class _Try { is = { defined: (prop) => this.filter((v) => isDefined(prop ? prop(v) : v)), empty: (prop) => this.filter((v) => isEmpty(prop ? prop(v) : v)), valid: (prop) => this.filter((v) => validate(prop ? prop(v) : v).isValid), true: (prop) => this.filter((v) => isTrue(prop ? prop(v) : v)), false: (prop) => this.filter((v) => !isTrue(prop ? prop(v) : v)), not: { defined: (prop) => this.filter((v) => !isDefined(prop ? prop(v) : v)), empty: (prop) => this.filter((v) => !isEmpty(prop ? prop(v) : v)), valid: (prop) => this.filter((v) => !validate(prop ? prop(v) : v).isValid) } }; if = this.is; static of = (c, ...args) => { try { const out = ofGet(c, ...args); return new Success(out instanceof _Try ? out.value : out); } catch (e) { return new Failure(e); } }; }; var Success = class extends Try { constructor(value) { super(); this.value = value; } get error() { throw new Error("No error found"); } get isValid() { return true; } map(f) { return tryTo(f, this.value); } recover(f) { return this; } recoverFrom(type, f) { return this; } accept(f) { return tryTo(() => { f(this.value); return this; }); } filter(predicate) { return tryTo(() => { if (predicate(this.value)) return this; throw new Error(`Applying filter(${predicate.toString()}) failed.`); }); } or(value) { return this.value; } orElse(value) { return this.value; } orThrow(_error) { return this.value; } }; var Failure = class _Failure extends Try { constructor(error) { super(); this.error = error; } get value() { throw this.error; } get isValid() { return false; } map(f) { return new _Failure(this.error); } recover(f) { return tryTo(f, this.error); } recoverFrom(type, f) { return tryTo(() => this.error instanceof type ? this.recover(f) : this); } accept(f) { return this; } filter(predicate) { return this; } or(value) { return ofGet(value); } orElse(value) { return ofGet(value); } orThrow(error) { throw ofConstruct(error); } }; var tryTo = (c, ...args) => Try.of(c, ...args); // src/types/Case.ts var CaseBuilder = class { constructor(v) { this.v = v; } case(pred, out) { return new Case(this.v).case(pred, out); } type(guard, out) { return new Case(this.v).type(guard, out); } equals(value, out) { return new Case(this.v).equals(value, out); } is = { defined: (prop, out) => new Case(this.v).case(isDefined(prop(this.v)), out), empty: (prop, out) => new Case(this.v).case(isEmpty(prop(this.v)), out), valid: (prop, out) => new Case(this.v).case(validate(prop(this.v)).isValid, out), not: { defined: (prop, out) => new Case(this.v).case(!isDefined(prop(this.v)), out), empty: (prop, out) => new Case(this.v).case(!isEmpty(prop(this.v)), out), valid: (prop, out) => new Case(this.v).case(!validate(prop(this.v)).isValid, out) } }; if = this.is; }; var Case = class _Case { constructor(value, outcome) { this.value = value; this.outcome = outcome; } case(pred, out) { return tryTo(pred, this.value).is.true().map(() => ofGet(out, this.value)).map((res) => new Found(this.value, res)).or(this); } type(guard, out) { return tryTo(guard, this.value).is.true().map(() => out(this.value)).map((res) => new Found(this.value, res)).or(this); } equals(value, out) { return this.case(this.value === value, out); } is = { defined: (prop, out) => new _Case(this.value).case(isDefined(prop(this.value)), out), empty: (prop, out) => new _Case(this.value).case(isEmpty(prop(this.value)), out), valid: (prop, out) => new _Case(this.value).case(validate(prop(this.value)).isValid, out), not: { defined: (prop, out) => new _Case(this.value).case(!isDefined(prop(this.value)), out), empty: (prop, out) => new _Case(this.value).case(!isEmpty(prop(this.value)), out), valid: (prop, out) => new _Case(this.value).case(!validate(prop(this.value)).isValid, out) } }; if = this.is; else(alt) { return ofGet(alt, this.value); } }; var Found = class extends Case { constructor(value, outcome) { super(value, outcome); this.value = value; this.outcome = outcome; } case(pred, out) { return this; } type(guard, out) { return this; } equals(value, out) { return this; } is = { defined: (_prop, _out) => this, empty: (_prop, _out) => this, valid: (_prop, _out) => this, not: { defined: (_prop, _out) => this, empty: (_prop, _out) => this, valid: (_prop, _out) => this } }; if = this.is; else(alt) { return this.outcome; } }; var choose = (value) => new CaseBuilder(value); // src/validation/Validate.ts var asResults = (subject, template, options = {}) => toResults(toResult(text(template).parse(subject, options), toName(subject))); var validators = (subject) => meta(subject).keys("constraint").reduce((list, vs) => list.add(vs), toList()); var runValidator = (v, subject) => { try { const actual = isFunction(subject[v.property]) ? subject[v.property]() : subject[v.property]; const constraint = v.constraint(actual); return isResults(constraint) ? constraint : !constraint ? asResults(subject, v.text, { ...v, actual }) : toResults(); } catch (e) { return asResults(subject, asString(e)); } }; var constraints = (subject) => validators(subject).map((vs) => runValidator(vs, subject)).reduce((rs, r) => rs.add(...r.results), toResults()); var validate = (subject) => choose(subject).is.not.defined( (s) => s, () => toResults("Subject is not defined.") ).type(isEnum, (e) => e.isValid ? toResults() : asResults(e, "This is not a valid {type}.")).type(isValue, (v) => v.isValid ? toResults() : asResults(v, "This is not a valid {type}.")).type(isArray, (a) => a.map((i) => validate(i)).reduce((rs, r) => rs.add(...r.results), toResults())).type(isValidatable, (v) => constraints(v)).else(toResults()); var validateReject = (subject) => when(subject).not.isValid.reject(); var isValid = (t) => validate(t).isValid; // src/validation/When.ts var When = class _When { constructor(subject, valid = true, results) { this.subject = subject; this.valid = valid; this.results = results; } get not() { return this.clone(!this.valid); } get and() { return this.clone(this.valid); } get isDefined() { return this.clone(this.valid === isDefined(this.subject)); } get isEmpty() { return this.clone(this.valid === isEmpty(this.subject)); } get isTrue() { return this.clone(this.valid === !!this.subject); } get isValid() { this.results = validate(this.subject); return this.clone(this.valid === this.results.isValid); } isInstance = (c) => this.clone(this.valid === this.subject instanceof c); with = (pred) => this.clone(this.valid === ofGet(pred, this.subject)); contains = (property) => this.clone(this.valid === isDefined(ofGet(property, this.subject))); in = (...items) => this.clone(this.valid === isIn(this.subject, toArray(...items))); is = (item) => this.clone(this.valid === (this.subject === item)); reject = (error) => !this.valid ? resolve(this.subject) : reject(ofGet(error, this.subject) ?? this.results ?? Exception.Unknown); recover = (f) => resolve(!this.valid ? this.subject : f(this.subject)); clone = (result = true) => new _When(this.subject, result, this.results); }; var when = (subject) => new When(subject); export { When, when, Try, tryTo, choose, asResults, validate, validateReject, isValid }; //# sourceMappingURL=chunk-XAIHCZT4.mjs.map