From 723fa00cb14513eb1a517728d4464c4f148a29cc Mon Sep 17 00:00:00 2001 From: Elizabeth Alexander Hunt Date: Mon, 12 May 2025 09:40:12 -0700 Subject: The big refactor --- utils/trace.ts | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 utils/trace.ts (limited to 'utils/trace.ts') diff --git a/utils/trace.ts b/utils/trace.ts new file mode 100644 index 0000000..737aa60 --- /dev/null +++ b/utils/trace.ts @@ -0,0 +1,111 @@ +export interface Logger { + log: (...args: unknown[]) => void; + debug: (...args: unknown[]) => void; + warn: (...args: unknown[]) => void; + error: (...args: unknown[]) => void; +} + +type Supplier = () => T; +type TraceSupplier = Supplier; +export interface ITraceableLogger> + extends Logger { + addTracer: (traceSupplier: TraceSupplier) => L; +} + +export type ITraceableTuple = [T, TraceSupplier]; +export type ITraceableMapper, U> = ( + t: ITraceable, +) => U; +export interface ITraceable> { + item: T; + logger: L; + + map: (mapper: ITraceableMapper) => ITraceable; + bimap: ( + mapper: ITraceableMapper>, + ) => ITraceable; + peek: (peek: ITraceableMapper) => ITraceable; + flatMap: (mapper: ITraceableMapper>) => ITraceable; + flatMapAsync(mapper: ITraceableMapper>>): ITraceable, L>; +} + +export class TraceableLogger + implements ITraceableLogger { + private readonly logger: Logger = console; + constructor( + private readonly traces = [() => `[${new Date().toISOString()}]`], + ) { + } + + public debug(...args: unknown[]) { + this.logger.debug("[DEBUG]", ...this.getPrefix(), args); + } + + public log(...args: unknown[]) { + this.logger.log("[INFO]", ...this.getPrefix(), args); + } + + public warn(...args: unknown[]) { + this.logger.warn("[WARN]", ...this.getPrefix(), args); + } + + public error(...args: unknown[]) { + this.logger.error("[ERROR]", ...this.getPrefix(), args); + } + + public addTracer(traceSupplier: TraceSupplier) { + return new TraceableLogger(this.traces.concat(traceSupplier)); + } + + private getPrefix() { + return this.traces.map((tracer) => tracer()); + } +} + +export class TraceableImpl< + T, + L extends ITraceableLogger, +> implements ITraceable { + private constructor(readonly item: T, readonly logger: L) {} + + public map(mapper: ITraceableMapper) { + const result = mapper(this); + return new TraceableImpl(result, this.logger); + } + + public flatMap(mapper: ITraceableMapper>): ITraceable { + return mapper(this); + } + + public flatMapAsync(mapper: ITraceableMapper>>): ITraceable, L> { + return new TraceableImpl(mapper(this).then((i) => ) + } + + public peek(peek: ITraceableMapper) { + peek(this); + return this; + } + + public bimap(mapper: ITraceableMapper>) { + const [item, trace] = mapper(this); + return new TraceableImpl(item, this.logger.addTracer(trace)); + } + + static promiseify, U>( + mapper: ITraceableMapper, + ): ITraceableMapper, L, Promise> { + return (traceablePromise) => traceablePromise.map( + async ({ item: promise }) => { + const t = await promise; + return traceablePromise.map(() => t).map(mapper).item; + }); +// return (traceable) => +// traceable.item.then((item) => mapper(new TraceableImpl(item, traceable.logger))); + } + + static from(t: T) { + return new TraceableImpl(t, new TraceableLogger()); + } +} + +export interface Traceable extends ITraceable -- cgit v1.2.3-70-g09d2