import { BaseRequest, Either, IEither, LogMetricTraceable, Metric, PenguenoRequest, Server, Signals, TraceUtil, } from '@emprespresso/pengueno'; import { serve, ServerType } from '@hono/node-server'; import { Hono } from 'hono'; const AppLifetimeMetric = Metric.fromName('HonoAppLifetime').asResult(); const AppRequestMetric = Metric.fromName('HonoAppRequest'); export class HonoProxy { private readonly app = LogMetricTraceable.of(new Hono()) .flatMap(TraceUtil.withTrace(`AppId = ${crypto.randomUUID()}`)) .flatMap(TraceUtil.withMetricTrace(AppLifetimeMetric)); constructor(private readonly server: Server) {} public async serve(port: number, hostname: string): Promise> { return this.app .map((tApp) => Either.fromFailable(() => { const app = tApp.get(); app.all('*', async (c) => tApp .flatMap(TraceUtil.withMetricTrace(AppRequestMetric)) .move(c.req) .flatMap((tRequest) => PenguenoRequest.from(tRequest)) .map((req) => this.server.serve(req)) .map( TraceUtil.promiseify((tResponse) => { tResponse.trace.trace(AppRequestMetric.count.withValue(1.0)); return new Response(tResponse.get().body(), tResponse.get()); }), ) .get(), ); return serve({ fetch: (_r) => app.fetch(_r), port, hostname, }); }), ) .peek(TraceUtil.traceResultingEither()) .peek((tServe) => tServe .get() .mapRight(() => tServe.trace.trace( `haii im still listening at http://${hostname}:${port} ~uwu dont think i forgot`, ), ), ) .map((tEitherServer) => tEitherServer .get() .mapRight((server) => tEitherServer.move(server)) .flatMapAsync((tServer) => Signals.awaitClose(tServer)), ) .peek(TraceUtil.promiseify(TraceUtil.traceResultingEither(AppLifetimeMetric))) .get(); } }