import { Either, type IEither, type ITraceable, LogLevel, Metric, PenguenoError, type PenguenoRequest, type RequestFilter, type ServerTrace, TraceUtil, } from "@emprespresso/pengueno"; export interface JsonTransformer { (json: ITraceable): IEither; } const ParseJsonMetric = Metric.fromName("JsonParse"); export const jsonModel = ( jsonTransformer: JsonTransformer, ): RequestFilter => (r: ITraceable) => r.bimap(TraceUtil.withMetricTrace(ParseJsonMetric)) .map((j) => Either.fromFailableAsync(j.get().json()) .then((either) => either.mapLeft((errReason) => { j.trace.addTrace(LogLevel.WARN).trace(`${errReason}`); return new PenguenoError( "seems to be invalid JSON (>//<) can you fix?", 400, ); }) ) ) .peek( TraceUtil.promiseify((traceableEither) => traceableEither.get().mapBoth( () => traceableEither.trace.trace(ParseJsonMetric.failure), () => traceableEither.trace.trace(ParseJsonMetric.success), ) ), ) .map( TraceUtil.promiseify((traceableEitherJson) => traceableEitherJson.get() .mapRight(traceableEitherJson.move) .flatMap(jsonTransformer) ), ) .get();