diff options
Diffstat (limited to 'u/server/filter/json.ts')
-rw-r--r-- | u/server/filter/json.ts | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/u/server/filter/json.ts b/u/server/filter/json.ts new file mode 100644 index 0000000..4a2961e --- /dev/null +++ b/u/server/filter/json.ts @@ -0,0 +1,51 @@ +import { + Either, + type IEither, + type ITraceable, + LogLevel, + Metric, + PenguenoError, + type PenguenoRequest, + type RequestFilter, + type ServerTrace, + TraceUtil, +} from "@emprespresso/pengueno"; + +export interface JsonTransformer<R, ParsedJson = unknown> { + (json: ITraceable<ParsedJson, ServerTrace>): IEither<PenguenoError, R>; +} + +const ParseJsonMetric = Metric.fromName("JsonParse"); +export const jsonModel = <MessageT>( + jsonTransformer: JsonTransformer<MessageT>, +): RequestFilter<MessageT> => +(r: ITraceable<PenguenoRequest, ServerTrace>) => + r.bimap(TraceUtil.withMetricTrace(ParseJsonMetric)) + .map((j) => + Either.fromFailableAsync<Error, MessageT>(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(); |