summaryrefslogtreecommitdiff
path: root/u/server/filter
diff options
context:
space:
mode:
Diffstat (limited to 'u/server/filter')
-rw-r--r--u/server/filter/json.ts43
-rw-r--r--u/server/filter/method.ts10
-rw-r--r--u/server/filter/mod.ts28
3 files changed, 50 insertions, 31 deletions
diff --git a/u/server/filter/json.ts b/u/server/filter/json.ts
index c839707..4a2961e 100644
--- a/u/server/filter/json.ts
+++ b/u/server/filter/json.ts
@@ -3,46 +3,49 @@ import {
type IEither,
type ITraceable,
LogLevel,
+ Metric,
+ PenguenoError,
type PenguenoRequest,
type RequestFilter,
type ServerTrace,
TraceUtil,
} from "@emprespresso/pengueno";
-import { Metric } from "../../trace/mod.ts";
-type JsonTransformer<R, ParsedJson = unknown> = (
- json: ITraceable<ParsedJson, ServerTrace>,
-) => IEither<Error, R>;
+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, Error> =>
+): RequestFilter<MessageT> =>
(r: ITraceable<PenguenoRequest, ServerTrace>) =>
- r
- .bimap(TraceUtil.withMetricTrace(ParseJsonMetric))
+ 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 Error("seems to be invalid JSON (>//<) can you fix?");
+ return new PenguenoError(
+ "seems to be invalid JSON (>//<) can you fix?",
+ 400,
+ );
})
)
)
- .flatMapAsync(
- TraceUtil.promiseify((traceableEitherJson) =>
- traceableEitherJson.map((t) =>
- t.get().mapRight(traceableEitherJson.move).flatMap(
- jsonTransformer,
- )
+ .peek(
+ TraceUtil.promiseify((traceableEither) =>
+ traceableEither.get().mapBoth(
+ () => traceableEither.trace.trace(ParseJsonMetric.failure),
+ () => traceableEither.trace.trace(ParseJsonMetric.success),
)
),
)
- .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();
diff --git a/u/server/filter/method.ts b/u/server/filter/method.ts
index 350f04c..6b0419d 100644
--- a/u/server/filter/method.ts
+++ b/u/server/filter/method.ts
@@ -1,8 +1,8 @@
import {
Either,
type ITraceable,
- JsonResponse,
LogLevel,
+ PenguenoError,
type PenguenoRequest,
type RequestFilter,
type ServerTrace,
@@ -22,7 +22,7 @@ type HttpMethod =
export const requireMethod = (
methods: Array<HttpMethod>,
-): RequestFilter<HttpMethod, JsonResponse> =>
+): RequestFilter<HttpMethod> =>
(req: ITraceable<PenguenoRequest, ServerTrace>) =>
req.bimap(TraceUtil.withFunctionTrace(requireMethod))
.move(Promise.resolve(req.get()))
@@ -32,10 +32,10 @@ export const requireMethod = (
if (!methods.includes(method)) {
const msg = "that's not how you pet me (â‹Ÿīšâ‹ž)~";
t.trace.addTrace(LogLevel.WARN).trace(msg);
- return Either.left<JsonResponse, HttpMethod>(
- new JsonResponse(req, msg, { status: 405 }),
+ return Either.left<PenguenoError, HttpMethod>(
+ new PenguenoError(msg, 405),
);
}
- return Either.right<JsonResponse, HttpMethod>(method);
+ return Either.right<PenguenoError, HttpMethod>(method);
}))
.get();
diff --git a/u/server/filter/mod.ts b/u/server/filter/mod.ts
index 22ddad5..bbf37df 100644
--- a/u/server/filter/mod.ts
+++ b/u/server/filter/mod.ts
@@ -1,13 +1,29 @@
-import type {
- IEither,
- ITraceable,
- PenguenoRequest,
- ServerTrace,
+import {
+ type IEither,
+ type ITraceable,
+ LogLevel,
+ type PenguenoRequest,
+ type ServerTrace,
} from "@emprespresso/pengueno";
+export enum ErrorSource {
+ USER = LogLevel.WARN,
+ SYSTEM = LogLevel.ERROR,
+}
+
+export class PenguenoError extends Error {
+ public readonly source: ErrorSource;
+ constructor(message: string, public readonly status: number) {
+ super(message);
+ this.source = Math.floor(status / 100) === 4
+ ? ErrorSource.USER
+ : ErrorSource.SYSTEM;
+ }
+}
+
export interface RequestFilter<
T,
- Err,
+ Err extends PenguenoError = PenguenoError,
RIn = ITraceable<PenguenoRequest, ServerTrace>,
> {
(req: RIn): Promise<IEither<Err, T>>;