diff options
Diffstat (limited to 'u')
-rw-r--r-- | u/fn/either.ts | 183 | ||||
-rw-r--r-- | u/process/argv.ts | 13 | ||||
-rw-r--r-- | u/server/activity/health.ts | 12 | ||||
-rw-r--r-- | u/server/response.ts | 4 |
4 files changed, 117 insertions, 95 deletions
diff --git a/u/fn/either.ts b/u/fn/either.ts index b228af2..124557c 100644 --- a/u/fn/either.ts +++ b/u/fn/either.ts @@ -1,97 +1,118 @@ -import type { BiMapper, Mapper, Supplier } from "@emprespresso/pengueno"; -import { isObject } from "../leftpadesque/mod.ts"; +import { type Mapper, type Supplier, isObject } from "@emprespresso/pengueno"; type IEitherTag = "IEither"; const iEitherTag: IEitherTag = "IEither"; +export interface _Either<LeftT, RightT, T> { + readonly isLeft: LeftT; + readonly isRight: RightT; + readonly value: T; +} +export type Left<E> = _Either<true, false, E>; +export type Right<T> = _Either<false, true, T>; + export interface IEither<E, T> { - readonly _tag: IEitherTag; - mapBoth: <Ee, Tt>( - errBranch: Mapper<E, Ee>, - okBranch: Mapper<T, Tt>, - ) => IEither<Ee, Tt>; - fold: <Tt>(folder: (err: E | undefined, val: T | undefined) => Tt) => Tt; //BiMapper<E | undefined, T | undefined, Tt>) => Tt;; - moveRight: <Tt>(t: Tt) => IEither<E, Tt>; - mapRight: <Tt>(mapper: Mapper<T, Tt>) => IEither<E, Tt>; - mapLeft: <Ee>(mapper: Mapper<E, Ee>) => IEither<Ee, T>; - flatMap: <Tt>(mapper: Mapper<T, IEither<E, Tt>>) => IEither<E, Tt>; - flatMapAsync: <Tt>( - mapper: Mapper<T, Promise<IEither<E, Tt>>>, - ) => Promise<IEither<E, Tt>>; + readonly _tag: IEitherTag; + + mapBoth: <_E, _T>( + errBranch: Mapper<E, _E>, + okBranch: Mapper<T, _T>, + ) => IEither<_E, _T>; + fold: <_T>(folder: Mapper<Left<E> | Right<T>, _T>) => _T; + moveRight: <_T>(t: _T) => IEither<E, _T>; + mapRight: <_T>(mapper: Mapper<T, _T>) => IEither<E, _T>; + mapLeft: <_E>(mapper: Mapper<E, _E>) => IEither<_E, T>; + flatMap: <_T>(mapper: Mapper<T, IEither<E, _T>>) => IEither<E, _T>; + flatMapAsync: <_T>( + mapper: Mapper<T, Promise<IEither<E, _T>>>, + ) => Promise<IEither<E, _T>>; } export class Either<E, T> implements IEither<E, T> { - private constructor( - private readonly err?: E, - private readonly ok?: T, - public readonly _tag: IEitherTag = iEitherTag, - ) {} - - public moveRight<Tt>(t: Tt) { - return this.mapRight(() => t); - } - - public fold<R>(folder: BiMapper<E | undefined, T | undefined, R>): R { - return folder(this.err ?? undefined, this.ok ?? undefined); - } - - public mapBoth<Ee, Tt>( - errBranch: Mapper<E, Ee>, - okBranch: Mapper<T, Tt>, - ): Either<Ee, Tt> { - if (this.err !== undefined) return Either.left(errBranch(this.err)); - return Either.right(okBranch(this.ok!)); - } - - public flatMap<Tt>(mapper: Mapper<T, Either<E, Tt>>): Either<E, Tt> { - if (this.ok !== undefined) return mapper(this.ok); - return Either.left<E, Tt>(this.err!); - } - - public mapRight<Tt>(mapper: Mapper<T, Tt>): IEither<E, Tt> { - if (this.ok !== undefined) return Either.right<E, Tt>(mapper(this.ok)); - return Either.left<E, Tt>(this.err!); - } - - public mapLeft<Ee>(mapper: Mapper<E, Ee>): IEither<Ee, T> { - if (this.err !== undefined) return Either.left<Ee, T>(mapper(this.err)); - return Either.right<Ee, T>(this.ok!); - } - - public async flatMapAsync<Tt>( - mapper: Mapper<T, Promise<IEither<E, Tt>>>, - ): Promise<IEither<E, Tt>> { - if (this.err !== undefined) { - return Promise.resolve(Either.left<E, Tt>(this.err)); + private readonly self: Left<E> | Right<T>; + + private constructor( + err?: E, + ok?: T, + public readonly _tag: IEitherTag = iEitherTag, + ) { + this.self = <Left<E> | Right<T>>{ + isLeft: typeof err !== "undefined", + isRight: typeof ok !== "undefined", + value: typeof err !== "undefined" ? err : ok!, + }; + } + + public moveRight<_T>(t: _T) { + return this.mapRight(() => t); + } + + public fold<_T>(folder: Mapper<Left<E> | Right<T>, _T>): _T { + return folder(this.self); + } + + public mapBoth<_E, _T>( + errBranch: Mapper<E, _E>, + okBranch: Mapper<T, _T>, + ): IEither<_E, _T> { + if (this.self.isLeft) return Either.left(errBranch(this.self.value)); + return Either.right(okBranch(this.self.value)); + } + + public flatMap<_T>(mapper: Mapper<T, IEither<E, _T>>): IEither<E, _T> { + if (this.self.isRight) return mapper(this.self.value); + return Either.left<E, _T>(this.self.value); + } + + public mapRight<_T>(mapper: Mapper<T, _T>): IEither<E, _T> { + if (this.self.isRight) + return Either.right<E, _T>(mapper(this.self.value)); + return Either.left<E, _T>(this.self.value); } - return await mapper(this.ok!).catch((err) => Either.left<E, Tt>(err as E)); - } - - static left<E, T>(e: E) { - return new Either<E, T>(e); - } - - static right<E, T>(t: T) { - return new Either<E, T>(undefined, t); - } - - static fromFailable<E, T>(s: Supplier<T>) { - try { - return Either.right<E, T>(s()); - } catch (e) { - return Either.left<E, T>(e as E); + + public mapLeft<_E>(mapper: Mapper<E, _E>): IEither<_E, T> { + if (this.self.isLeft) + return Either.left<_E, T>(mapper(this.self.value)); + return Either.right<_E, T>(this.self.value); + } + + public async flatMapAsync<_T>( + mapper: Mapper<T, Promise<IEither<E, _T>>>, + ): Promise<IEither<E, _T>> { + if (this.self.isLeft) { + return Promise.resolve(Either.left<E, _T>(this.self.value)); + } + return await mapper(this.self.value).catch((err) => + Either.left<E, _T>(err), + ); + } + + static left<E, T>(e: E): IEither<E, T> { + return new Either<E, T>(e, undefined); + } + static right<E, T>(t: T): IEither<E, T> { + return new Either<E, T>(undefined, t); + } + + static fromFailable<E, T>(s: Supplier<T>): IEither<E, T> { + try { + return Either.right<E, T>(s()); + } catch (e) { + return Either.left<E, T>(e as E); + } } - } - static async fromFailableAsync<E, T>(s: Promise<T>) { - try { - return Either.right<E, T>(await s); - } catch (e) { - return Either.left<E, T>(e as E); + static async fromFailableAsync<E, T>( + s: Promise<T>, + ): Promise<IEither<E, T>> { + try { + return Either.right<E, T>(await s); + } catch (e) { + return Either.left<E, T>(e as E); + } } - } } export const isEither = <E, T>(o: unknown): o is IEither<E, T> => { - return isObject(o) && "_tag" in o && o._tag === "IEither"; + return isObject(o) && "_tag" in o && o._tag === "IEither"; }; diff --git a/u/process/argv.ts b/u/process/argv.ts index 657c9a7..7190531 100644 --- a/u/process/argv.ts +++ b/u/process/argv.ts @@ -37,14 +37,15 @@ export const argv = <K extends string, V extends string>( .map((arg) => [arg, getArg(arg, argv)] as [K, IEither<Error, V>]) .map(([arg, specified]): [K, IEither<Error, V>] => [ arg, - specified.fold((e, val) => { - const hasDefaultVal = e && defaultArgs && arg in defaultArgs; + specified.fold(({ isLeft, isRight, value}): IEither<Error, V> => { + if (isRight) { + return Either.right(value); + } + const hasDefaultVal = isLeft && defaultArgs && arg in defaultArgs; if (hasDefaultVal) { - return Either.right<Error, V>(defaultArgs[arg]!); - } else if (!val || e) { - return Either.left<Error, V>(e ?? new Error("unknown")); + return Either.right(defaultArgs[arg]!); } - return Either.right<Error, V>(val); + return Either.left(value); }), ]) .reduce( diff --git a/u/server/activity/health.ts b/u/server/activity/health.ts index 83be399..b9dedf9 100644 --- a/u/server/activity/health.ts +++ b/u/server/activity/health.ts @@ -38,10 +38,10 @@ export class HealthCheckActivityImpl implements IHealthCheckActivity { .flatMap((r) => r.move(HealthCheckInput.CHECK).map(this.check)) .peek( TraceUtil.promiseify((h) => - h.get().fold((err) => { - if (err) { + h.get().fold(({ isLeft, value }) => { + if (isLeft) { h.trace.trace(healthCheckMetric.failure); - h.trace.addTrace(LogLevel.ERROR).trace(`${err}`); + h.trace.addTrace(LogLevel.ERROR).trace(`${value}`); return; } h.trace.trace(healthCheckMetric.success); @@ -57,9 +57,9 @@ export class HealthCheckActivityImpl implements IHealthCheckActivity { () => "think im healthy!! (✿˘◡˘) ready to do work~", ) .fold( - (errMsg, okMsg) => - new JsonResponse(req, errMsg ?? okMsg, { - status: errMsg ? 500 : 200, + ({ isLeft, value: message }) => + new JsonResponse(req, message, { + status: isLeft ? 500 : 200, }), ), ), diff --git a/u/server/response.ts b/u/server/response.ts index 9022fed..4531157 100644 --- a/u/server/response.ts +++ b/u/server/response.ts @@ -67,7 +67,7 @@ export class JsonResponse extends PenguenoResponse { super( req, JSON.stringify( - e.fold((err, ok) => (err ? { error: err! } : { ok: ok! })), + e.fold(({ isLeft, value }) => (isLeft ? { error: value } : { ok: value })), ), optsWithJsonContentType, ); @@ -76,7 +76,7 @@ export class JsonResponse extends PenguenoResponse { super( req, JSON.stringify( - Math.floor(opts.status / 100) < 4 ? { ok: e } : { error: e }, + Math.floor(opts.status / 100) > 4 ? { error: e } : { ok: e }, ), optsWithJsonContentType, ); |