Skip to main content
Glama
ssv445

Lorem Ipsum MCP Server

by ssv445
logger.ts15.6 kB
import * as Arr from "../Array.js" import * as Context from "../Context.js" import * as FiberRefs from "../FiberRefs.js" import type { LazyArg } from "../Function.js" import { constVoid, dual } from "../Function.js" import { globalValue } from "../GlobalValue.js" import * as HashMap from "../HashMap.js" import * as Inspectable from "../Inspectable.js" import * as List from "../List.js" import type * as Logger from "../Logger.js" import type * as LogLevel from "../LogLevel.js" import * as Option from "../Option.js" import { pipeArguments } from "../Pipeable.js" import * as Cause from "./cause.js" import * as defaultServices from "./defaultServices.js" import { consoleTag } from "./defaultServices/console.js" import * as fiberId_ from "./fiberId.js" import * as logSpan_ from "./logSpan.js" /** @internal */ const LoggerSymbolKey = "effect/Logger" /** @internal */ export const LoggerTypeId: Logger.LoggerTypeId = Symbol.for( LoggerSymbolKey ) as Logger.LoggerTypeId const loggerVariance = { /* c8 ignore next */ _Message: (_: unknown) => _, /* c8 ignore next */ _Output: (_: never) => _ } /** @internal */ export const makeLogger = <Message, Output>( log: (options: Logger.Logger.Options<Message>) => Output ): Logger.Logger<Message, Output> => ({ [LoggerTypeId]: loggerVariance, log, pipe() { return pipeArguments(this, arguments) } }) /** @internal */ export const mapInput = dual< <Message, Message2>( f: (message: Message2) => Message ) => <Output>(self: Logger.Logger<Message, Output>) => Logger.Logger<Message2, Output>, <Output, Message, Message2>( self: Logger.Logger<Message, Output>, f: (message: Message2) => Message ) => Logger.Logger<Message2, Output> >(2, (self, f) => makeLogger( (options) => self.log({ ...options, message: f(options.message) }) )) /** @internal */ export const mapInputOptions = dual< <Message, Message2>( f: (options: Logger.Logger.Options<Message2>) => Logger.Logger.Options<Message> ) => <Output>(self: Logger.Logger<Message, Output>) => Logger.Logger<Message2, Output>, <Output, Message, Message2>( self: Logger.Logger<Message, Output>, f: (options: Logger.Logger.Options<Message2>) => Logger.Logger.Options<Message> ) => Logger.Logger<Message2, Output> >(2, (self, f) => makeLogger((options) => self.log(f(options)))) /** @internal */ export const filterLogLevel = dual< ( f: (logLevel: LogLevel.LogLevel) => boolean ) => <Message, Output>(self: Logger.Logger<Message, Output>) => Logger.Logger<Message, Option.Option<Output>>, <Message, Output>( self: Logger.Logger<Message, Output>, f: (logLevel: LogLevel.LogLevel) => boolean ) => Logger.Logger<Message, Option.Option<Output>> >(2, (self, f) => makeLogger((options) => f(options.logLevel) ? Option.some(self.log(options)) : Option.none() )) /** @internal */ export const map = dual< <Output, Output2>( f: (output: Output) => Output2 ) => <Message>(self: Logger.Logger<Message, Output>) => Logger.Logger<Message, Output2>, <Message, Output, Output2>( self: Logger.Logger<Message, Output>, f: (output: Output) => Output2 ) => Logger.Logger<Message, Output2> >(2, (self, f) => makeLogger((options) => f(self.log(options)))) /** @internal */ export const none: Logger.Logger<unknown, void> = { [LoggerTypeId]: loggerVariance, log: constVoid, pipe() { return pipeArguments(this, arguments) } } as Logger.Logger<unknown, void> /** @internal */ export const simple = <A, B>(log: (a: A) => B): Logger.Logger<A, B> => ({ [LoggerTypeId]: loggerVariance, log: ({ message }) => log(message), pipe() { return pipeArguments(this, arguments) } }) /** @internal */ export const succeed = <A>(value: A): Logger.Logger<unknown, A> => { return simple(() => value) } /** @internal */ export const sync = <A>(evaluate: LazyArg<A>): Logger.Logger<unknown, A> => { return simple(evaluate) } /** @internal */ export const zip = dual< <Message2, Output2>( that: Logger.Logger<Message2, Output2> ) => <Message, Output>( self: Logger.Logger<Message, Output> ) => Logger.Logger<Message & Message2, [Output, Output2]>, <Message, Output, Message2, Output2>( self: Logger.Logger<Message, Output>, that: Logger.Logger<Message2, Output2> ) => Logger.Logger<Message & Message2, [Output, Output2]> >(2, (self, that) => makeLogger((options) => [self.log(options), that.log(options)])) /** @internal */ export const zipLeft = dual< <Message2, Output2>( that: Logger.Logger<Message2, Output2> ) => <Message, Output>( self: Logger.Logger<Message, Output> ) => Logger.Logger<Message & Message2, Output>, <Message, Output, Message2, Output2>( self: Logger.Logger<Message, Output>, that: Logger.Logger<Message2, Output2> ) => Logger.Logger<Message & Message2, Output> >(2, (self, that) => map(zip(self, that), (tuple) => tuple[0])) /** @internal */ export const zipRight = dual< <Message2, Output2>( that: Logger.Logger<Message2, Output2> ) => <Message, Output>( self: Logger.Logger<Message, Output> ) => Logger.Logger<Message & Message2, Output2>, <Message, Output, Message2, Output2>( self: Logger.Logger<Message, Output>, that: Logger.Logger<Message2, Output2> ) => Logger.Logger<Message & Message2, Output2> >(2, (self, that) => map(zip(self, that), (tuple) => tuple[1])) /** * Match strings that do not contain any whitespace characters, double quotes, * or equal signs. * * @internal */ const textOnly = /^[^\s"=]*$/ /** * Used by both {@link stringLogger} and {@link logfmtLogger} to render a log * message. * * @internal */ const format = (quoteValue: (s: string) => string, whitespace?: number | string | undefined) => ( { annotations, cause, date, fiberId, logLevel, message, spans }: Logger.Logger.Options<unknown> ): string => { const formatValue = (value: string): string => value.match(textOnly) ? value : quoteValue(value) const format = (label: string, value: string): string => `${logSpan_.formatLabel(label)}=${formatValue(value)}` const append = (label: string, value: string): string => " " + format(label, value) let out = format("timestamp", date.toISOString()) out += append("level", logLevel.label) out += append("fiber", fiberId_.threadName(fiberId)) const messages = Arr.ensure(message) for (let i = 0; i < messages.length; i++) { out += append("message", Inspectable.toStringUnknown(messages[i], whitespace)) } if (!Cause.isEmptyType(cause)) { out += append("cause", Cause.pretty(cause, { renderErrorCause: true })) } for (const span of spans) { out += " " + logSpan_.render(date.getTime())(span) } for (const [label, value] of annotations) { out += append(label, Inspectable.toStringUnknown(value, whitespace)) } return out } /** @internal */ const escapeDoubleQuotes = (s: string) => `"${s.replace(/\\([\s\S])|(")/g, "\\$1$2")}"` /** @internal */ export const stringLogger: Logger.Logger<unknown, string> = makeLogger(format(escapeDoubleQuotes)) /** @internal */ export const logfmtLogger: Logger.Logger<unknown, string> = makeLogger(format(JSON.stringify, 0)) /** @internal */ export const structuredLogger = makeLogger<unknown, { readonly logLevel: string readonly fiberId: string readonly timestamp: string readonly message: unknown readonly cause: string | undefined readonly annotations: Record<string, unknown> readonly spans: Record<string, number> }>( ({ annotations, cause, date, fiberId, logLevel, message, spans }) => { const now = date.getTime() const annotationsObj: Record<string, unknown> = {} const spansObj: Record<string, number> = {} if (HashMap.size(annotations) > 0) { for (const [k, v] of annotations) { annotationsObj[k] = structuredMessage(v) } } if (List.isCons(spans)) { for (const span of spans) { spansObj[span.label] = now - span.startTime } } const messageArr = Arr.ensure(message) return { message: messageArr.length === 1 ? structuredMessage(messageArr[0]) : messageArr.map(structuredMessage), logLevel: logLevel.label, timestamp: date.toISOString(), cause: Cause.isEmpty(cause) ? undefined : Cause.pretty(cause, { renderErrorCause: true }), annotations: annotationsObj, spans: spansObj, fiberId: fiberId_.threadName(fiberId) } } ) /** @internal */ export const structuredMessage = (u: unknown): unknown => { switch (typeof u) { case "bigint": case "function": case "symbol": { return String(u) } default: { return Inspectable.toJSON(u) } } } /** @internal */ export const jsonLogger = map(structuredLogger, Inspectable.stringifyCircular) /** @internal */ export const isLogger = (u: unknown): u is Logger.Logger<unknown, unknown> => { return typeof u === "object" && u != null && LoggerTypeId in u } const withColor = (text: string, ...colors: ReadonlyArray<string>) => { let out = "" for (let i = 0; i < colors.length; i++) { out += `\x1b[${colors[i]}m` } return out + text + "\x1b[0m" } const withColorNoop = (text: string, ..._colors: ReadonlyArray<string>) => text const colors = { bold: "1", red: "31", green: "32", yellow: "33", blue: "34", cyan: "36", white: "37", gray: "90", black: "30", bgBrightRed: "101" } as const const logLevelColors: Record<LogLevel.LogLevel["_tag"], ReadonlyArray<string>> = { None: [], All: [], Trace: [colors.gray], Debug: [colors.blue], Info: [colors.green], Warning: [colors.yellow], Error: [colors.red], Fatal: [colors.bgBrightRed, colors.black] } const logLevelStyle: Record<LogLevel.LogLevel["_tag"], string> = { None: "", All: "", Trace: "color:gray", Debug: "color:blue", Info: "color:green", Warning: "color:orange", Error: "color:red", Fatal: "background-color:red;color:white" } const defaultDateFormat = (date: Date): string => `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}:${ date.getSeconds().toString().padStart(2, "0") }.${date.getMilliseconds().toString().padStart(3, "0")}` const hasProcessStdout = typeof process === "object" && process !== null && typeof process.stdout === "object" && process.stdout !== null const processStdoutIsTTY = hasProcessStdout && process.stdout.isTTY === true const hasProcessStdoutOrDeno = hasProcessStdout || "Deno" in globalThis /** @internal */ export const prettyLogger = (options?: { readonly colors?: "auto" | boolean | undefined readonly stderr?: boolean | undefined readonly formatDate?: ((date: Date) => string) | undefined readonly mode?: "browser" | "tty" | "auto" | undefined }) => { const mode_ = options?.mode ?? "auto" const mode = mode_ === "auto" ? (hasProcessStdoutOrDeno ? "tty" : "browser") : mode_ const isBrowser = mode === "browser" const showColors = typeof options?.colors === "boolean" ? options.colors : processStdoutIsTTY || isBrowser const formatDate = options?.formatDate ?? defaultDateFormat return isBrowser ? prettyLoggerBrowser({ colors: showColors, formatDate }) : prettyLoggerTty({ colors: showColors, formatDate, stderr: options?.stderr === true }) } const prettyLoggerTty = (options: { readonly colors: boolean readonly stderr: boolean readonly formatDate: (date: Date) => string }) => { const processIsBun = typeof process === "object" && "isBun" in process && process.isBun === true const color = options.colors ? withColor : withColorNoop return makeLogger<unknown, void>( ({ annotations, cause, context, date, fiberId, logLevel, message: message_, spans }) => { const services = FiberRefs.getOrDefault(context, defaultServices.currentServices) const console = Context.get(services, consoleTag).unsafe const log = options.stderr === true ? console.error : console.log const message = Arr.ensure(message_) let firstLine = color(`[${options.formatDate(date)}]`, colors.white) + ` ${color(logLevel.label, ...logLevelColors[logLevel._tag])}` + ` (${fiberId_.threadName(fiberId)})` if (List.isCons(spans)) { const now = date.getTime() const render = logSpan_.render(now) for (const span of spans) { firstLine += " " + render(span) } } firstLine += ":" let messageIndex = 0 if (message.length > 0) { const firstMaybeString = structuredMessage(message[0]) if (typeof firstMaybeString === "string") { firstLine += " " + color(firstMaybeString, colors.bold, colors.cyan) messageIndex++ } } log(firstLine) if (!processIsBun) console.group() if (!Cause.isEmpty(cause)) { log(Cause.pretty(cause, { renderErrorCause: true })) } if (messageIndex < message.length) { for (; messageIndex < message.length; messageIndex++) { log(Inspectable.redact(message[messageIndex])) } } if (HashMap.size(annotations) > 0) { for (const [key, value] of annotations) { log(color(`${key}:`, colors.bold, colors.white), Inspectable.redact(value)) } } if (!processIsBun) console.groupEnd() } ) } const prettyLoggerBrowser = (options: { readonly colors: boolean readonly formatDate: (date: Date) => string }) => { const color = options.colors ? "%c" : "" return makeLogger<unknown, void>( ({ annotations, cause, context, date, fiberId, logLevel, message: message_, spans }) => { const services = FiberRefs.getOrDefault(context, defaultServices.currentServices) const console = Context.get(services, consoleTag).unsafe const message = Arr.ensure(message_) let firstLine = `${color}[${options.formatDate(date)}]` const firstParams = [] if (options.colors) { firstParams.push("color:gray") } firstLine += ` ${color}${logLevel.label}${color} (${fiberId_.threadName(fiberId)})` if (options.colors) { firstParams.push(logLevelStyle[logLevel._tag], "") } if (List.isCons(spans)) { const now = date.getTime() const render = logSpan_.render(now) for (const span of spans) { firstLine += " " + render(span) } } firstLine += ":" let messageIndex = 0 if (message.length > 0) { const firstMaybeString = structuredMessage(message[0]) if (typeof firstMaybeString === "string") { firstLine += ` ${color}${firstMaybeString}` if (options.colors) { firstParams.push("color:deepskyblue") } messageIndex++ } } console.groupCollapsed(firstLine, ...firstParams) if (!Cause.isEmpty(cause)) { console.error(Cause.pretty(cause, { renderErrorCause: true })) } if (messageIndex < message.length) { for (; messageIndex < message.length; messageIndex++) { console.log(Inspectable.redact(message[messageIndex])) } } if (HashMap.size(annotations) > 0) { for (const [key, value] of annotations) { const redacted = Inspectable.redact(value) if (options.colors) { console.log(`%c${key}:`, "color:gray", redacted) } else { console.log(`${key}:`, redacted) } } } console.groupEnd() } ) } /** @internal */ export const prettyLoggerDefault = globalValue("effect/Logger/prettyLoggerDefault", () => prettyLogger())

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ssv445/lorem-ipsum-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server