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();