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.withFunctionTrace(jsonModel)) .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().fold(({ isLeft }) => traceableEither.trace.trace(ParseJsonMetric[isLeft ? "failure" : "success"]) ), ), ) .map( TraceUtil.promiseify((traceableEitherJson) => traceableEitherJson .get() .mapRight((j) => traceableEitherJson.move(j)) .flatMap(jsonTransformer), ), ) .get();