diff options
author | Elizabeth Alexander Hunt <me@liz.coffee> | 2025-05-12 09:40:12 -0700 |
---|---|---|
committer | Elizabeth <me@liz.coffee> | 2025-05-26 14:15:42 -0700 |
commit | d51c9d74857aca3c2f172609297266968bc7f809 (patch) | |
tree | 64327f9cc4219729aa11af32d7d4c70cddfc2292 /u/server/response.ts | |
parent | 30729a0cf707d9022bae0a7baaba77379dc31fd5 (diff) | |
download | ci-d51c9d74857aca3c2f172609297266968bc7f809.tar.gz ci-d51c9d74857aca3c2f172609297266968bc7f809.zip |
The big refactor TM
Diffstat (limited to 'u/server/response.ts')
-rw-r--r-- | u/server/response.ts | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/u/server/response.ts b/u/server/response.ts new file mode 100644 index 0000000..c21819a --- /dev/null +++ b/u/server/response.ts @@ -0,0 +1,84 @@ +import { + type IEither, + isEither, + type ITraceable, + Metric, + type PenguenoRequest, + type ServerTrace, +} from "@emprespresso/pengueno"; + +export type ResponseBody = object | string; +export type TResponseInit = ResponseInit & { + status: number; + headers?: Record<string, string>; +}; + +const getResponse = ( + req: PenguenoRequest, + opts: TResponseInit, +): TResponseInit => { + return { + ...opts, + headers: { + ...(req.baseResponseHeaders()), + ...(opts?.headers), + "Content-Type": (opts?.headers?.["Content-Type"] ?? "text/plain") + + "; charset=utf-8", + }, + }; +}; + +const ResponseCodeMetrics = [1, 2, 3, 4, 5].map((x) => + Metric.fromName(`response.${x}xx`) +); +export const getResponseMetric = (status: number) => { + const index = (Math.floor(status / 100)) + 1; + return ResponseCodeMetrics[index] ?? ResponseCodeMetrics[5 - 1]; +}; + +export class PenguenoResponse extends Response { + constructor( + req: ITraceable<PenguenoRequest, ServerTrace>, + msg: BodyInit, + opts: TResponseInit, + ) { + const responseOpts = getResponse(req.get(), opts); + const resMetric = getResponseMetric(opts.status); + req.trace.trace(resMetric.count.withValue(1.0)); + responseOpts.headers; + super(msg, responseOpts); + } +} + +export class JsonResponse extends PenguenoResponse { + constructor( + req: ITraceable<PenguenoRequest, ServerTrace>, + e: BodyInit | IEither<ResponseBody, ResponseBody>, + opts: TResponseInit, + ) { + const optsWithJsonContentType = { + ...opts, + headers: { + ...opts?.headers, + "Content-Type": "application/json", + }, + }; + if (isEither<ResponseBody, ResponseBody>(e)) { + super( + req, + JSON.stringify( + e.fold((err, ok) => err ? ({ error: err! }) : ({ ok: ok! })), + ), + optsWithJsonContentType, + ); + return; + } + super( + req, + JSON.stringify( + (Math.floor(opts.status / 100) < 4) ? { ok: e } : { error: e }, + ), + optsWithJsonContentType, + ); + } +} |