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