summaryrefslogtreecommitdiff
path: root/u/server
diff options
context:
space:
mode:
Diffstat (limited to 'u/server')
-rw-r--r--u/server/activity/fourohfour.ts28
-rw-r--r--u/server/activity/health.ts49
-rw-r--r--u/server/activity/index.ts8
-rw-r--r--u/server/filter/index.ts34
-rw-r--r--u/server/filter/json.ts42
-rw-r--r--u/server/filter/method.ts30
-rw-r--r--u/server/http/body.ts10
-rw-r--r--u/server/http/index.ts3
-rw-r--r--u/server/http/method.ts1
-rw-r--r--u/server/http/status.ts71
-rw-r--r--u/server/index.ts13
-rw-r--r--u/server/request/index.ts18
-rw-r--r--u/server/request/pengueno.ts44
-rw-r--r--u/server/response/index.ts18
-rw-r--r--u/server/response/json_pengueno.ts29
-rw-r--r--u/server/response/pengueno.ts59
16 files changed, 0 insertions, 457 deletions
diff --git a/u/server/activity/fourohfour.ts b/u/server/activity/fourohfour.ts
deleted file mode 100644
index cd90ba0..0000000
--- a/u/server/activity/fourohfour.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import {
- type IActivity,
- type ITraceable,
- JsonResponse,
- type PenguenoRequest,
- type ServerTrace,
-} from '@emprespresso/pengueno';
-
-const messages = [
- 'D: meow-t found! your api call ran away!',
- '404-bidden! but like...in a cute way >:3 !',
- ':< your data went on a paw-sible vacation!',
- 'uwu~ not found, but found our hearts instead!',
-];
-const randomFourOhFour = () => messages[Math.floor(Math.random() * messages.length)]!;
-
-export interface IFourOhFourActivity {
- fourOhFour: IActivity;
-}
-
-export class FourOhFourActivityImpl implements IFourOhFourActivity {
- public fourOhFour(req: ITraceable<PenguenoRequest, ServerTrace>) {
- return req
- .move(new JsonResponse(req, randomFourOhFour(), { status: 404 }))
- .map((resp) => Promise.resolve(resp.get()))
- .get();
- }
-}
diff --git a/u/server/activity/health.ts b/u/server/activity/health.ts
deleted file mode 100644
index 9396490..0000000
--- a/u/server/activity/health.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import {
- type IActivity,
- type IEither,
- IMetric,
- type ITraceable,
- JsonResponse,
- LogLevel,
- type Mapper,
- Metric,
- type PenguenoRequest,
- type ServerTrace,
- TraceUtil,
-} from '@emprespresso/pengueno';
-
-export enum HealthCheckInput {
- CHECK,
-}
-export enum HealthCheckOutput {
- YAASSSLAYQUEEN,
-}
-
-export interface IHealthCheckActivity {
- checkHealth: IActivity;
-}
-
-const healthCheckMetric = Metric.fromName('Health').asResult();
-export interface HealthChecker
- extends Mapper<ITraceable<HealthCheckInput, ServerTrace>, Promise<IEither<Error, HealthCheckOutput>>> {}
-export class HealthCheckActivityImpl implements IHealthCheckActivity {
- constructor(private readonly check: HealthChecker) {}
-
- public checkHealth(req: ITraceable<PenguenoRequest, ServerTrace>) {
- return req
- .flatMap(TraceUtil.withFunctionTrace(this.checkHealth))
- .flatMap(TraceUtil.withMetricTrace(healthCheckMetric))
- .flatMap((r) => r.move(HealthCheckInput.CHECK).map((input) => this.check(input)))
- .peek(TraceUtil.promiseify(TraceUtil.traceResultingEither(healthCheckMetric)))
- .map(
- TraceUtil.promiseify((h) => {
- const { status, message } = h.get().fold(
- () => ({ status: 500, message: 'err' }),
- () => ({ status: 200, message: 'ok' }),
- );
- return new JsonResponse(req, message, { status });
- }),
- )
- .get();
- }
-}
diff --git a/u/server/activity/index.ts b/u/server/activity/index.ts
deleted file mode 100644
index fa0a6b2..0000000
--- a/u/server/activity/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { ITraceable, PenguenoRequest, PenguenoResponse, ServerTrace } from '@emprespresso/pengueno';
-
-export interface IActivity {
- (req: ITraceable<PenguenoRequest, ServerTrace>): Promise<PenguenoResponse>;
-}
-
-export * from './health.js';
-export * from './fourohfour.js';
diff --git a/u/server/filter/index.ts b/u/server/filter/index.ts
deleted file mode 100644
index 75168c7..0000000
--- a/u/server/filter/index.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-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(
- override readonly message: string,
- public readonly status: number,
- ) {
- super(message);
- this.source = Math.floor(status / 100) === 4 ? ErrorSource.USER : ErrorSource.SYSTEM;
- }
-}
-
-export interface RequestFilter<
- T,
- Err extends PenguenoError = PenguenoError,
- RIn = ITraceable<PenguenoRequest, ServerTrace>,
-> {
- (req: RIn): IEither<Err, T> | Promise<IEither<Err, T>>;
-}
-
-export * from './method.js';
-export * from './json.js';
diff --git a/u/server/filter/json.ts b/u/server/filter/json.ts
deleted file mode 100644
index bc53d47..0000000
--- a/u/server/filter/json.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-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').asResult();
-export const jsonModel =
- <MessageT>(jsonTransformer: JsonTransformer<MessageT>): RequestFilter<MessageT> =>
- (r: ITraceable<PenguenoRequest, ServerTrace>) =>
- r
- .flatMap(TraceUtil.withFunctionTrace(jsonModel))
- .flatMap(TraceUtil.withMetricTrace(ParseJsonMetric))
- .map((j) =>
- Either.fromFailableAsync<Error, MessageT>(<Promise<MessageT>>j.get().req.json()).then((either) =>
- either.mapLeft((errReason) => {
- j.trace.traceScope(LogLevel.WARN).trace(errReason);
- return new PenguenoError('seems to be invalid JSON (>//<) can you fix?', 400);
- }),
- ),
- )
- .flatMapAsync(TraceUtil.promiseify(TraceUtil.traceResultingEither(ParseJsonMetric)))
- .map(
- TraceUtil.promiseify((traceableEitherJson) =>
- traceableEitherJson
- .get()
- .mapRight((j) => traceableEitherJson.move(j))
- .flatMap(jsonTransformer),
- ),
- )
- .get();
diff --git a/u/server/filter/method.ts b/u/server/filter/method.ts
deleted file mode 100644
index 7d6aa76..0000000
--- a/u/server/filter/method.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import {
- Either,
- HttpMethod,
- IEither,
- type ITraceable,
- LogLevel,
- PenguenoError,
- type PenguenoRequest,
- type RequestFilter,
- type ServerTrace,
- TraceUtil,
-} from '@emprespresso/pengueno';
-
-export const requireMethod =
- (methods: Array<HttpMethod>): RequestFilter<HttpMethod> =>
- (req: ITraceable<PenguenoRequest, ServerTrace>) =>
- req
- .flatMap(TraceUtil.withFunctionTrace(requireMethod))
- .map((t): IEither<PenguenoError, HttpMethod> => {
- const {
- req: { method },
- } = t.get();
- if (!methods.includes(method)) {
- const msg = "that's not how you pet me (â‹Ÿīšâ‹ž)~";
- t.trace.traceScope(LogLevel.WARN).trace(msg);
- return Either.left(new PenguenoError(msg, 405));
- }
- return Either.right(method);
- })
- .get();
diff --git a/u/server/http/body.ts b/u/server/http/body.ts
deleted file mode 100644
index 5fc4caa..0000000
--- a/u/server/http/body.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-export type Body =
- | ArrayBuffer
- | AsyncIterable<Uint8Array>
- | Blob
- | FormData
- | Iterable<Uint8Array>
- | NodeJS.ArrayBufferView
- | URLSearchParams
- | null
- | string;
diff --git a/u/server/http/index.ts b/u/server/http/index.ts
deleted file mode 100644
index ef1c039..0000000
--- a/u/server/http/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './body.js';
-export * from './status.js';
-export * from './method.js';
diff --git a/u/server/http/method.ts b/u/server/http/method.ts
deleted file mode 100644
index 172d77a..0000000
--- a/u/server/http/method.ts
+++ /dev/null
@@ -1 +0,0 @@
-export type HttpMethod = 'POST' | 'GET' | 'HEAD' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE' | 'PATCH';
diff --git a/u/server/http/status.ts b/u/server/http/status.ts
deleted file mode 100644
index 15cb30c..0000000
--- a/u/server/http/status.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-export const HttpStatusCodes: Record<number, string> = {
- 100: 'Continue',
- 101: 'Switching Protocols',
- 102: 'Processing (WebDAV)',
- 200: 'OK',
- 201: 'Created',
- 202: 'Accepted',
- 203: 'Non-Authoritative Information',
- 204: 'No Content',
- 205: 'Reset Content',
- 206: 'Partial Content',
- 207: 'Multi-Status (WebDAV)',
- 208: 'Already Reported (WebDAV)',
- 226: 'IM Used',
- 300: 'Multiple Choices',
- 301: 'Moved Permanently',
- 302: 'Found',
- 303: 'See Other',
- 304: 'Not Modified',
- 305: 'Use Proxy',
- 306: '(Unused)',
- 307: 'Temporary Redirect',
- 308: 'Permanent Redirect (experimental)',
- 400: 'Bad Request',
- 401: 'Unauthorized',
- 402: 'Payment Required',
- 403: 'Forbidden',
- 404: 'Not Found',
- 405: 'Method Not Allowed',
- 406: 'Not Acceptable',
- 407: 'Proxy Authentication Required',
- 408: 'Request Timeout',
- 409: 'Conflict',
- 410: 'Gone',
- 411: 'Length Required',
- 412: 'Precondition Failed',
- 413: 'Request Entity Too Large',
- 414: 'Request-URI Too Long',
- 415: 'Unsupported Media Type',
- 416: 'Requested Range Not Satisfiable',
- 417: 'Expectation Failed',
- 418: "I'm a teapot (RFC 2324)",
- 420: 'Enhance Your Calm (Twitter)',
- 422: 'Unprocessable Entity (WebDAV)',
- 423: 'Locked (WebDAV)',
- 424: 'Failed Dependency (WebDAV)',
- 425: 'Reserved for WebDAV',
- 426: 'Upgrade Required',
- 428: 'Precondition Required',
- 429: 'Too Many Requests',
- 431: 'Request Header Fields Too Large',
- 444: 'No Response (Nginx)',
- 449: 'Retry With (Microsoft)',
- 450: 'Blocked by Windows Parental Controls (Microsoft)',
- 451: 'Unavailable For Legal Reasons',
- 499: 'Client Closed Request (Nginx)',
- 500: 'Internal Server Error',
- 501: 'Not Implemented',
- 502: 'Bad Gateway',
- 503: 'Service Unavailable',
- 504: 'Gateway Timeout',
- 505: 'HTTP Version Not Supported',
- 506: 'Variant Also Negotiates (Experimental)',
- 507: 'Insufficient Storage (WebDAV)',
- 508: 'Loop Detected (WebDAV)',
- 509: 'Bandwidth Limit Exceeded (Apache)',
- 510: 'Not Extended',
- 511: 'Network Authentication Required',
- 598: 'Network read timeout error',
- 599: 'Network connect timeout error',
-};
diff --git a/u/server/index.ts b/u/server/index.ts
deleted file mode 100644
index 1cefb71..0000000
--- a/u/server/index.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import type { ITraceable, LogMetricTraceSupplier, Mapper } from '@emprespresso/pengueno';
-export type ServerTrace = LogMetricTraceSupplier;
-
-export * from './http/index.js';
-export * from './response/index.js';
-export * from './request/index.js';
-export * from './activity/index.js';
-export * from './filter/index.js';
-
-import { PenguenoRequest, PenguenoResponse } from '@emprespresso/pengueno';
-export interface Server {
- readonly serve: Mapper<ITraceable<PenguenoRequest, ServerTrace>, Promise<PenguenoResponse>>;
-}
diff --git a/u/server/request/index.ts b/u/server/request/index.ts
deleted file mode 100644
index 41d59b7..0000000
--- a/u/server/request/index.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { HttpMethod } from '@emprespresso/pengueno';
-
-export interface BaseRequest {
- url: string;
- method: HttpMethod;
-
- header(): Record<string, string>;
-
- formData(): Promise<FormData>;
- json(): Promise<unknown>;
- text(): Promise<string>;
-
- param(key: string): string | undefined;
- query(): Record<string, string>;
- queries(): Record<string, string[]>;
-}
-
-export * from './pengueno.js';
diff --git a/u/server/request/pengueno.ts b/u/server/request/pengueno.ts
deleted file mode 100644
index 31563e9..0000000
--- a/u/server/request/pengueno.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { BaseRequest, ITraceable, ServerTrace } from '@emprespresso/pengueno';
-
-const greetings = ['hewwo :D', 'hiya cutie', 'boop!', 'sending virtual hugs!', 'stay pawsitive'];
-const penguenoGreeting = () => greetings[Math.floor(Math.random() * greetings.length)];
-
-export class PenguenoRequest {
- private constructor(
- public readonly req: BaseRequest,
- private readonly id: string,
- private readonly at: Date,
- ) {}
-
- public elapsedTimeMs(after = () => Date.now()): number {
- return after() - this.at.getTime();
- }
-
- public getResponseHeaders(): Record<string, string> {
- const RequestId = this.id;
- const RequestReceivedUnix = this.at.getTime();
- const RequestHandleUnix = Date.now();
- const DeltaUnix = this.elapsedTimeMs(() => RequestHandleUnix);
- const Hai = penguenoGreeting();
-
- return Object.entries({
- RequestId,
- RequestReceivedUnix,
- RequestHandleUnix,
- DeltaUnix,
- Hai,
- }).reduce((acc, [key, val]) => ({ ...acc, [key]: val!.toString() }), {});
- }
-
- public static from(request: ITraceable<BaseRequest, ServerTrace>): ITraceable<PenguenoRequest, ServerTrace> {
- const id = crypto.randomUUID();
- return request.bimap((tRequest) => {
- const request = tRequest.get();
- const url = new URL(request.url);
- const { pathname } = url;
- const trace = `RequestId = ${id}, Method = ${request.method}, Path = ${pathname}`;
-
- return { item: new PenguenoRequest(request, id, new Date()), trace };
- });
- }
-}
diff --git a/u/server/response/index.ts b/u/server/response/index.ts
deleted file mode 100644
index 17a2d97..0000000
--- a/u/server/response/index.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { Body } from '@emprespresso/pengueno';
-
-export interface BaseResponse {
- status: number;
- statusText: string;
- headers: Record<string, string>;
-
- body(): Body;
-}
-
-export interface ResponseOpts {
- status: number;
- statusText?: string;
- headers?: Record<string, string>;
-}
-
-export * from './pengueno.js';
-export * from './json_pengueno.js';
diff --git a/u/server/response/json_pengueno.ts b/u/server/response/json_pengueno.ts
deleted file mode 100644
index d0b74a8..0000000
--- a/u/server/response/json_pengueno.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import {
- isEither,
- ITraceable,
- PenguenoRequest,
- PenguenoResponse,
- ResponseOpts,
- ServerTrace,
-} from '@emprespresso/pengueno';
-
-type Jsonable = any;
-export class JsonResponse extends PenguenoResponse {
- constructor(req: ITraceable<PenguenoRequest, ServerTrace>, e: Jsonable, _opts: ResponseOpts) {
- const opts = { ..._opts, headers: { ..._opts.headers, 'Content-Type': 'application/json' } };
- if (isEither<Jsonable, Jsonable>(e)) {
- super(
- req,
- JSON.stringify(
- e.fold(
- (error) => ({ error, ok: undefined }),
- (ok) => ({ ok }),
- ),
- ),
- opts,
- );
- return;
- }
- super(req, JSON.stringify(Math.floor(opts.status / 100) > 4 ? { error: e } : { ok: e }), opts);
- }
-}
diff --git a/u/server/response/pengueno.ts b/u/server/response/pengueno.ts
deleted file mode 100644
index 5a953db..0000000
--- a/u/server/response/pengueno.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import {
- BaseResponse,
- Body,
- HttpStatusCodes,
- ITraceable,
- Metric,
- Optional,
- PenguenoRequest,
- ResponseOpts,
- ServerTrace,
-} from '@emprespresso/pengueno';
-
-const getHeaders = (req: PenguenoRequest, extraHeaders: Record<string, string>) => {
- const optHeaders = {
- ...req.getResponseHeaders(),
- ...extraHeaders,
- };
- optHeaders['Content-Type'] = (optHeaders['Content-Type'] ?? 'text/plain') + '; charset=utf-8';
- return optHeaders;
-};
-
-const ResponseCodeMetrics = [0, 1, 2, 3, 4, 5].map((x) => Metric.fromName(`response.${x}xx`).asResult());
-export const getResponseMetrics = (status: number, elapsedMs?: number) => {
- const index = Math.floor(status / 100);
- return ResponseCodeMetrics.flatMap((metric, i) =>
- Optional.from(i)
- .filter((i) => i === index)
- .map(() => [metric.count.withValue(1.0)])
- .flatMap((metricValues) =>
- Optional.from(elapsedMs)
- .map((ms) => metricValues.concat(metric.time.withValue(ms)))
- .orSome(() => metricValues),
- )
- .orSome(() => [metric.count.withValue(0.0)])
- .get(),
- );
-};
-
-export class PenguenoResponse implements BaseResponse {
- public readonly statusText: string;
- public readonly status: number;
- public readonly headers: Record<string, string>;
-
- constructor(
- req: ITraceable<PenguenoRequest, ServerTrace>,
- private readonly _body: Body,
- opts: ResponseOpts,
- ) {
- this.headers = getHeaders(req.get(), opts?.headers ?? {});
- this.status = opts.status;
- this.statusText = opts.statusText ?? HttpStatusCodes[this.status]!;
-
- req.trace.trace(getResponseMetrics(opts.status, req.get().elapsedTimeMs()));
- }
-
- public body() {
- return this._body;
- }
-}