@jumpaku/async-result
Version:
A typescript library that provides Result, Option, and AsyncResult.
1 lines • 7.8 kB
JavaScript
import{BaseError}from"make-error-cause";class Some{constructor(s){this.value=s,this.length=1,this[0]=this.value,this[Symbol.iterator]=()=>{const s=this.value;return function*(){yield s}()}}isSome(){return!0}isNone(){return!1}flatMap(s){return s(this.value)}map(s){return new Some(s(this.value))}orDefault(s){return this.value}orBuild(s){return this.value}orThrow(s){return this.value}orNull(){return this.value}orUndefined(){return this.value}takeIf(s){return s(this.value)?this:none()}takeIfNotNull(){return nonNull(this.value)}ifPresent(s){return s(this.value),this}ifAbsent(s){return this}and(s){return s}or(s){return this}}class None{constructor(){this.length=0,this[Symbol.iterator]=()=>function*(){}()}isSome(){return!1}isNone(){return!0}flatMap(s){return None.instance}map(s){return None.instance}orDefault(s){return s}orBuild(s){return s()}orThrow(s){throw null!=s?s():new Error("Option is None.")}orNull(){return null}orUndefined(){}takeIf(s){return this}takeIfNotNull(){return None.instance}ifPresent(s){return this}ifAbsent(s){return s(),this}and(s){return this}or(s){return s}}function none(){return None.instance}function some(s){return new Some(s)}function nonNull(s){return null!=s?some(s):none()}None.instance=new None;class AsyncResult{constructor(s){this.promise=s}static of(s,t){return Result.isResult(s)?new AsyncResult(Promise.resolve(s)):new AsyncResult(null==t?s.catch((s=>Result.failure(s))):s.catch((s=>Result.failure(t(s)))))}static make(s){return AsyncResult.of(new Promise((t=>s((s=>t(Result.success(s))),(s=>t(Result.failure(s)))))),(s=>s))}static success(s){return AsyncResult.of(Result.success(s))}static failure(s){return AsyncResult.of(Result.failure(s))}static try(s,t){const e=new Promise(((t,e)=>{try{t(s())}catch(s){e(s)}})).then(Result.success);return null==t?AsyncResult.of(e):AsyncResult.of(e,t)}then(s,t){return this.promise.then(s,t)}match(s,t){return this.promise.then((e=>e.match(s,t)))}value(){return this.promise.then((s=>s.value))}error(){return this.promise.then((s=>s.error))}orNull(){return this.promise.then((s=>s.orNull()))}orUndefined(){return this.promise.then((s=>s.orUndefined()))}orReject(s){return this.promise.then((t=>null==s?t.orThrow():t.orThrow(s)))}orDefault(s){return this.promise.then((t=>t.orDefault(s)))}orRecover(s){return this.promise.then((t=>t.orRecover(s)))}onSuccess(s){return this.promise.then((t=>t.onSuccess(s))),this}onFailure(s){return this.promise.then((t=>t.onFailure(s))),this}and(s){return new AsyncResult(this.promise.then((t=>s.promise.then((s=>t.and(s))))))}or(s){return new AsyncResult(this.promise.then((t=>s.promise.then((s=>t.or(s))))))}map(s){return new AsyncResult(this.promise.then((t=>t.map(s))))}tryMap(s,t){return(null==t?AsyncResult.try((()=>this.promise.then((t=>t.tryMap(s))))):AsyncResult.try((()=>this.promise.then((e=>e.tryMap(s,t)))),t)).flatMap((s=>AsyncResult.of(s)))}flatMap(s){const t=new Promise((async t=>{(await this.promise).onSuccess((e=>t(s(e).promise))).onFailure((s=>t(Result.failure(s))))}));return new AsyncResult(t)}tryFlatMap(s,t){if(null==t){const t=this.promise.then((async t=>t.isFailure()?t.castValue():s(t.value).promise)).catch((s=>Result.failure(s)));return AsyncResult.of(t)}{const e=this.promise.then((async t=>t.isFailure()?t.castValue():s(t.value).promise)).catch((s=>Result.failure(t(s))));return AsyncResult.of(e)}}recover(s){return new AsyncResult(this.promise.then((t=>t.recover(s))))}tryRecover(s,t){return null==t?AsyncResult.of(this.match(Result.success,(t=>Result.try((()=>s(t)))))):AsyncResult.of(this.match(Result.success,(e=>Result.try((()=>s(e)),t))))}flatRecover(s){const t=new Promise((async t=>{(await this.promise).onSuccess((s=>t(Result.success(s)))).onFailure((e=>t(s(e).promise)))}));return new AsyncResult(t)}tryFlatRecover(s,t){const e=new Promise((async e=>{(await this.promise).onSuccess((s=>e(Result.success(s)))).onFailure((r=>{try{e(s(r).promise)}catch(s){e(null==t?Result.failure(s):Result.failure(t(s)))}}))}));return new AsyncResult(e)}mapError(s){return new AsyncResult(this.promise.then((t=>t.mapError(s))))}tryMapError(s,t){return(null==t?AsyncResult.try((()=>this.promise.then((t=>t.tryMapError(s))))):AsyncResult.try((()=>this.promise.then((e=>e.tryMapError(s,t)))),t)).flatMap((s=>AsyncResult.of(s)))}}class ResultError extends BaseError{constructor(s){super(s instanceof Error?s.message:"",s instanceof Error?s:void 0),this.name="ResultError",this.detail=s}}const Result={success:s=>new Success(s),failure:s=>new Failure(s),try:(s,t)=>{try{return Result.success(s())}catch(s){return null==t?Result.failure(s):Result.failure(t(s))}},isResult:s=>s instanceof AbstractResult};class AbstractResult{assertsThisIsResult(){if(!this.isSuccess()&&!this.isFailure())throw new Error}match(s,t){return this.assertsThisIsResult(),this.isSuccess()?s(this.value):t(this.error)}orDefault(s){return this.isSuccess()?this.value:s}orRecover(s){return this.assertsThisIsResult(),this.isSuccess()?this.value:s(this.error)}orThrow(s){if(this.assertsThisIsResult(),this.isFailure())throw null!=s?s(this.error):new ResultError(this.error);return this.value}orNull(){return this.isSuccess()?this.value:null}orUndefined(){return this.isSuccess()?this.value:void 0}onSuccess(s){return this.isSuccess()&&s(this.value),this.assertsThisIsResult(),this}onFailure(s){return this.assertsThisIsResult(),this.isFailure()&&s(this.error),this}and(s){return this.isFailure()?this:s}or(s){return this.isSuccess()?this:s}map(s){return this.assertsThisIsResult(),this.isSuccess()?Result.success(s(this.value)):this.castValue()}mapAsync(s,t){return null==t?this.match((t=>AsyncResult.try((()=>s(t)))),(s=>AsyncResult.failure(s))):this.match((e=>AsyncResult.try((()=>s(e)),t)),(s=>AsyncResult.failure(s)))}tryMap(s,t){return(null==t?Result.try((()=>this.map(s))):Result.try((()=>this.map(s)),t)).flatMap((s=>s))}flatMap(s){return this.assertsThisIsResult(),this.isSuccess()?s(this.value):this.castValue()}flatMapAsync(s,t){if(this.assertsThisIsResult(),this.isFailure())return AsyncResult.of(this.castValue());try{const t=s(this.value);return Result.isResult(t)?AsyncResult.of(t):t}catch(s){return null==t?AsyncResult.failure(s):AsyncResult.failure(t(s))}}tryFlatMap(s,t){return(null==t?Result.try((()=>this.flatMap(s))):Result.try((()=>this.flatMap(s)),t)).flatMap((s=>s))}recover(s){return this.assertsThisIsResult(),this.isFailure()?Result.success(s(this.error)):this.castError()}recoverAsync(s,t){this.assertsThisIsResult();const e=async()=>(this.assertsThisIsResult(),this.isSuccess()?this.value:s(this.error));return null==t?AsyncResult.try(e):AsyncResult.try(e,t)}tryRecover(s,t){return(null==t?Result.try((()=>this.recover(s))):Result.try((()=>this.recover(s)),t)).flatMap((s=>s))}flatRecover(s){return this.assertsThisIsResult(),this.isFailure()?s(this.error):this.castError()}flatRecoverAsync(s,t){if(this.assertsThisIsResult(),this.isSuccess())return AsyncResult.of(this);try{const t=s(this.error);return Result.isResult(t)?AsyncResult.of(t):t}catch(s){return null==t?AsyncResult.failure(s):AsyncResult.failure(t(s))}}tryFlatRecover(s,t){return(null==t?Result.try((()=>this.flatRecover(s))):Result.try((()=>this.flatRecover(s)),t)).flatMap((s=>s))}mapError(s){return this.assertsThisIsResult(),this.isFailure()?Result.failure(s(this.error)):this.castError()}tryMapError(s,t){return(null==t?Result.try((()=>this.mapError(s))):Result.try((()=>this.mapError(s)),t)).flatMap((s=>s))}}class Success extends AbstractResult{constructor(s){super(),this.value=s,this.error=void 0}isSuccess(){return!0}isFailure(){return!1}castError(){return this}}class Failure extends AbstractResult{constructor(s){super(),this.error=s,this.value=void 0}isSuccess(){return!1}isFailure(){return!0}castValue(){return this}}export{AsyncResult,Failure,Result,ResultError,Success,nonNull,none,some};