UNPKG

@settlemint/sdk-utils

Version:

Shared utilities and helper functions for SettleMint SDK modules

1 lines 12.3 kB
{"version":3,"file":"logging.cjs","names":["output: string","options: LoggerOptions","logLevels: Record<LogLevel, number>","args: unknown[]","level: LogLevel","level","message: string","val: string","s: string","value: string","maxLength: number","logger: Logger","name: string","fn: typeof fetch","logger","duration: number","body: BodyInit","dataToKeep: Record<string, unknown>"],"sources":["../src/logging/mask-tokens.ts","../src/logging/logger.ts","../src/string.ts","../src/logging/request-logger.ts"],"sourcesContent":["/**\n * Masks sensitive SettleMint tokens in output text by replacing them with asterisks.\n * Handles personal access tokens (PAT), application access tokens (AAT), and service account tokens (SAT).\n *\n * @param output - The text string that may contain sensitive tokens\n * @returns The text with any sensitive tokens masked with asterisks\n * @example\n * import { maskTokens } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Masks a token in text\n * const masked = maskTokens(\"Token: sm_pat_****\"); // \"Token: ***\"\n */\nexport const maskTokens = (output: string): string => {\n return output.replace(/sm_(pat|aat|sat)_[0-9a-zA-Z]+/g, \"***\");\n};\n","import { maskTokens } from \"./mask-tokens.js\";\n\n/**\n * Log levels supported by the logger\n */\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"none\";\n\n/**\n * Configuration options for the logger\n * @interface LoggerOptions\n */\nexport interface LoggerOptions {\n /** The minimum log level to output */\n level?: LogLevel;\n /** The prefix to add to the log message */\n prefix?: string;\n}\n\n/**\n * Simple logger interface with basic logging methods\n * @interface Logger\n */\nexport interface Logger {\n /** Log debug information */\n debug: (message: string, ...args: unknown[]) => void;\n /** Log general information */\n info: (message: string, ...args: unknown[]) => void;\n /** Log warnings */\n warn: (message: string, ...args: unknown[]) => void;\n /** Log errors */\n error: (message: string, ...args: unknown[]) => void;\n}\n\n/**\n * Creates a simple logger with configurable log level\n *\n * @param options - Configuration options for the logger\n * @param options.level - The minimum log level to output (default: warn)\n * @param options.prefix - The prefix to add to the log message (default: \"\")\n * @returns A logger instance with debug, info, warn, and error methods\n *\n * @example\n * import { createLogger } from \"@/utils/logging/logger\";\n *\n * const logger = createLogger({ level: 'info' });\n *\n * logger.info('User logged in', { userId: '123' });\n * logger.error('Operation failed', new Error('Connection timeout'));\n */\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const { level = \"warn\", prefix = \"\" } = options;\n\n const logLevels: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n none: 4,\n };\n\n const currentLevelValue = logLevels[level];\n\n const formatArgs = (args: unknown[]): string => {\n if (args.length === 0 || args.every((arg) => arg === undefined || arg === null)) {\n return \"\";\n }\n\n const formatted = args\n .map((arg) => {\n if (arg instanceof Error) {\n return `\\n${arg.stack || arg.message}`;\n }\n if (typeof arg === \"object\" && arg !== null) {\n return `\\n${JSON.stringify(arg, null, 2)}`;\n }\n return ` ${String(arg)}`;\n })\n .join(\"\");\n\n return `, args:${formatted}`;\n };\n\n const shouldLog = (level: LogLevel): boolean => {\n return logLevels[level] >= currentLevelValue;\n };\n\n return {\n debug: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"debug\")) {\n console.debug(`\\x1b[32m${prefix}[DEBUG] ${maskTokens(message)}${maskTokens(formatArgs(args))}\\x1b[0m`);\n }\n },\n info: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"info\")) {\n console.info(`\\x1b[34m${prefix}[INFO] ${maskTokens(message)}${maskTokens(formatArgs(args))}\\x1b[0m`);\n }\n },\n warn: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"warn\")) {\n console.warn(`\\x1b[33m${prefix}[WARN] ${maskTokens(message)}${maskTokens(formatArgs(args))}\\x1b[0m`);\n }\n },\n error: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"error\")) {\n console.error(`\\x1b[31m${prefix}[ERROR] ${maskTokens(message)}${maskTokens(formatArgs(args))}\\x1b[0m`);\n }\n },\n };\n}\n\n/**\n * Default logger instance with standard configuration\n */\nexport const logger = createLogger();\n","/**\n * Capitalizes the first letter of a string.\n *\n * @param val - The string to capitalize\n * @returns The input string with its first letter capitalized\n *\n * @example\n * import { capitalizeFirstLetter } from \"@settlemint/sdk-utils\";\n *\n * const capitalized = capitalizeFirstLetter(\"hello\");\n * // Returns: \"Hello\"\n */\nexport function capitalizeFirstLetter(val: string) {\n return String(val).charAt(0).toUpperCase() + String(val).slice(1);\n}\n\n/**\n * Converts a camelCase string to a human-readable string.\n *\n * @param s - The camelCase string to convert\n * @returns The human-readable string\n *\n * @example\n * import { camelCaseToWords } from \"@settlemint/sdk-utils\";\n *\n * const words = camelCaseToWords(\"camelCaseString\");\n * // Returns: \"Camel Case String\"\n */\nexport function camelCaseToWords(s: string) {\n const result = s.replace(/([a-z])([A-Z])/g, \"$1 $2\");\n const withSpaces = result.replace(/([A-Z])([a-z])/g, \" $1$2\");\n const capitalized = capitalizeFirstLetter(withSpaces);\n return capitalized.replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Replaces underscores and hyphens with spaces.\n *\n * @param s - The string to replace underscores and hyphens with spaces\n * @returns The input string with underscores and hyphens replaced with spaces\n *\n * @example\n * import { replaceUnderscoresAndHyphensWithSpaces } from \"@settlemint/sdk-utils\";\n *\n * const result = replaceUnderscoresAndHyphensWithSpaces(\"Already_Spaced-Second\");\n * // Returns: \"Already Spaced Second\"\n */\nexport function replaceUnderscoresAndHyphensWithSpaces(s: string) {\n return s.replace(/[-_]/g, \" \");\n}\n\n/**\n * Truncates a string to a maximum length and appends \"...\" if it is longer.\n *\n * @param value - The string to truncate\n * @param maxLength - The maximum length of the string\n * @returns The truncated string or the original string if it is shorter than the maximum length\n *\n * @example\n * import { truncate } from \"@settlemint/sdk-utils\";\n *\n * const truncated = truncate(\"Hello, world!\", 10);\n * // Returns: \"Hello, wor...\"\n */\nexport function truncate(value: string, maxLength: number) {\n if (value.length <= maxLength) {\n return value;\n }\n return `${value.slice(0, maxLength)}...`;\n}\n","import { truncate } from \"../string.js\";\nimport type { Logger } from \"./logger.js\";\n\nconst WARNING_THRESHOLD = 500;\nconst TRUNCATE_LENGTH = 50;\n\n/**\n * Logs the request and duration of a fetch call (> 500ms is logged as warn, otherwise info)\n * @param logger - The logger to use\n * @param name - The name of the request\n * @param fn - The fetch function to use\n * @returns The fetch function\n */\nexport function requestLogger(logger: Logger, name: string, fn: typeof fetch) {\n return async (...args: Parameters<typeof fetch>) => {\n const start = Date.now();\n try {\n return await fn(...args);\n } finally {\n const end = Date.now();\n const duration = end - start;\n const body = extractInfoFromBody(args[1]?.body ?? \"{}\");\n const message = `${name} path: ${args[0]}, took ${formatDuration(duration)}`;\n if (duration > WARNING_THRESHOLD) {\n logger.warn(message, body);\n } else {\n logger.info(message, body);\n }\n }\n };\n}\n\nfunction formatDuration(duration: number) {\n return duration < 1000 ? `${duration}ms` : `${(duration / 1000).toFixed(3)}s`;\n}\n\nfunction extractInfoFromBody(body: BodyInit) {\n try {\n const parsedBody = typeof body === \"string\" ? JSON.parse(body) : body;\n\n if (parsedBody === null || parsedBody === undefined || Object.keys(parsedBody).length === 0) {\n return null;\n }\n\n const dataToKeep: Record<string, unknown> = {};\n // Check for graphql fields\n if (\"query\" in parsedBody) {\n dataToKeep.query = truncate(parsedBody.query, TRUNCATE_LENGTH);\n }\n if (\"variables\" in parsedBody) {\n dataToKeep.variables = truncate(JSON.stringify(parsedBody.variables), TRUNCATE_LENGTH);\n }\n if (\"operationName\" in parsedBody) {\n dataToKeep.operationName = truncate(parsedBody.operationName, TRUNCATE_LENGTH);\n }\n\n if (Object.keys(dataToKeep).length > 0) {\n return JSON.stringify(dataToKeep);\n }\n\n // Not graphql, return the body as is\n return truncate(JSON.stringify(parsedBody || \"{}\"), TRUNCATE_LENGTH);\n } catch {\n return \"{}\";\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAYA,MAAa,aAAa,CAACA,WAA2B;AACpD,QAAO,OAAO,QAAQ,kCAAkC,MAAM;AAC/D;;;;;;;;;;;;;;;;;;;;ACmCD,SAAgB,aAAaC,UAAyB,CAAE,GAAU;CAChE,MAAM,EAAE,QAAQ,QAAQ,SAAS,IAAI,GAAG;CAExC,MAAMC,YAAsC;EAC1C,OAAO;EACP,MAAM;EACN,MAAM;EACN,OAAO;EACP,MAAM;CACP;CAED,MAAM,oBAAoB,UAAU;CAEpC,MAAM,aAAa,CAACC,SAA4B;AAC9C,MAAI,KAAK,WAAW,KAAK,KAAK,MAAM,CAAC,QAAQ,QAAQ,aAAa,QAAQ,KAAK,EAAE;AAC/E,UAAO;EACR;EAED,MAAM,YAAY,KACf,IAAI,CAAC,QAAQ;AACZ,OAAI,eAAe,OAAO;AACxB,WAAO,CAAC,EAAE,EAAE,IAAI,SAAS,IAAI,SAAS;GACvC;AACD,OAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,WAAO,CAAC,EAAE,EAAE,KAAK,UAAU,KAAK,MAAM,EAAE,EAAE;GAC3C;AACD,UAAO,CAAC,CAAC,EAAE,OAAO,IAAI,EAAE;EACzB,EAAC,CACD,KAAK,GAAG;AAEX,SAAO,CAAC,OAAO,EAAE,WAAW;CAC7B;CAED,MAAM,YAAY,CAACC,YAA6B;AAC9C,SAAO,UAAUC,YAAU;CAC5B;AAED,QAAO;EACL,OAAO,CAACC,SAAiB,GAAG,SAAoB;AAC9C,OAAI,UAAU,QAAQ,EAAE;IACtB,QAAQ,MAAM,CAAC,QAAQ,EAAE,OAAO,QAAQ,EAAE,WAAW,QAAQ,GAAG,WAAW,WAAW,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC;GACvG;EACF;EACD,MAAM,CAACA,SAAiB,GAAG,SAAoB;AAC7C,OAAI,UAAU,OAAO,EAAE;IACrB,QAAQ,KAAK,CAAC,QAAQ,EAAE,OAAO,OAAO,EAAE,WAAW,QAAQ,GAAG,WAAW,WAAW,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC;GACrG;EACF;EACD,MAAM,CAACA,SAAiB,GAAG,SAAoB;AAC7C,OAAI,UAAU,OAAO,EAAE;IACrB,QAAQ,KAAK,CAAC,QAAQ,EAAE,OAAO,OAAO,EAAE,WAAW,QAAQ,GAAG,WAAW,WAAW,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC;GACrG;EACF;EACD,OAAO,CAACA,SAAiB,GAAG,SAAoB;AAC9C,OAAI,UAAU,QAAQ,EAAE;IACtB,QAAQ,MAAM,CAAC,QAAQ,EAAE,OAAO,QAAQ,EAAE,WAAW,QAAQ,GAAG,WAAW,WAAW,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC;GACvG;EACF;CACF;AACF;;;;AAKD,MAAa,SAAS,cAAc;;;;;;;;;;;;;;;;ACrGpC,SAAgB,sBAAsBC,KAAa;AACjD,QAAO,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,aAAa,GAAG,OAAO,IAAI,CAAC,MAAM,EAAE;AAClE;;;;;;;;;;;;;AAcD,SAAgB,iBAAiBC,GAAW;CAC1C,MAAM,SAAS,EAAE,QAAQ,mBAAmB,QAAQ;CACpD,MAAM,aAAa,OAAO,QAAQ,mBAAmB,QAAQ;CAC7D,MAAM,cAAc,sBAAsB,WAAW;AACrD,QAAO,YAAY,QAAQ,QAAQ,IAAI,CAAC,MAAM;AAC/C;;;;;;;;;;;;;AAcD,SAAgB,uCAAuCA,GAAW;AAChE,QAAO,EAAE,QAAQ,SAAS,IAAI;AAC/B;;;;;;;;;;;;;;AAeD,SAAgB,SAASC,OAAeC,WAAmB;AACzD,KAAI,MAAM,UAAU,WAAW;AAC7B,SAAO;CACR;AACD,QAAO,GAAG,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC;AACzC;;;;AClED,MAAM,oBAAoB;AAC1B,MAAM,kBAAkB;;;;;;;;AASxB,SAAgB,cAAcC,UAAgBC,MAAcC,IAAkB;AAC5E,QAAO,OAAO,GAAG,SAAmC;EAClD,MAAM,QAAQ,KAAK,KAAK;AACxB,MAAI;AACF,UAAO,MAAM,GAAG,GAAG,KAAK;EACzB,UAAS;GACR,MAAM,MAAM,KAAK,KAAK;GACtB,MAAM,WAAW,MAAM;GACvB,MAAM,OAAO,oBAAoB,KAAK,IAAI,QAAQ,KAAK;GACvD,MAAM,UAAU,GAAG,KAAK,OAAO,EAAE,KAAK,GAAG,OAAO,EAAE,eAAe,SAAS,EAAE;AAC5E,OAAI,WAAW,mBAAmB;IAChCC,SAAO,KAAK,SAAS,KAAK;GAC3B,OAAM;IACLA,SAAO,KAAK,SAAS,KAAK;GAC3B;EACF;CACF;AACF;AAED,SAAS,eAAeC,UAAkB;AACxC,QAAO,WAAW,MAAO,GAAG,SAAS,EAAE,CAAC,GAAG,IAAI,WAAW,KAAM,QAAQ,EAAE,CAAC,CAAC,CAAC;AAC9E;AAED,SAAS,oBAAoBC,MAAgB;AAC3C,KAAI;EACF,MAAM,aAAa,OAAO,SAAS,WAAW,KAAK,MAAM,KAAK,GAAG;AAEjE,MAAI,eAAe,QAAQ,eAAe,aAAa,OAAO,KAAK,WAAW,CAAC,WAAW,GAAG;AAC3F,UAAO;EACR;EAED,MAAMC,aAAsC,CAAE;AAE9C,MAAI,WAAW,YAAY;GACzB,WAAW,QAAQ,SAAS,WAAW,OAAO,gBAAgB;EAC/D;AACD,MAAI,eAAe,YAAY;GAC7B,WAAW,YAAY,SAAS,KAAK,UAAU,WAAW,UAAU,EAAE,gBAAgB;EACvF;AACD,MAAI,mBAAmB,YAAY;GACjC,WAAW,gBAAgB,SAAS,WAAW,eAAe,gBAAgB;EAC/E;AAED,MAAI,OAAO,KAAK,WAAW,CAAC,SAAS,GAAG;AACtC,UAAO,KAAK,UAAU,WAAW;EAClC;AAGD,SAAO,SAAS,KAAK,UAAU,cAAc,KAAK,EAAE,gBAAgB;CACrE,QAAO;AACN,SAAO;CACR;AACF"}