@settlemint/sdk-utils
Version:
Shared utilities and helper functions for SettleMint SDK modules
224 lines (219 loc) • 6.86 kB
JavaScript
//#region src/logging/mask-tokens.ts
/**
* Masks sensitive SettleMint tokens in output text by replacing them with asterisks.
* Handles personal access tokens (PAT), application access tokens (AAT), and service account tokens (SAT).
*
* @param output - The text string that may contain sensitive tokens
* @returns The text with any sensitive tokens masked with asterisks
* @example
* import { maskTokens } from "@settlemint/sdk-utils/terminal";
*
* // Masks a token in text
* const masked = maskTokens("Token: sm_pat_****"); // "Token: ***"
*/
const maskTokens = (output) => {
return output.replace(/sm_(pat|aat|sat)_[0-9a-zA-Z]+/g, "***");
};
//#endregion
//#region src/logging/logger.ts
/**
* Creates a simple logger with configurable log level
*
* @param options - Configuration options for the logger
* @param options.level - The minimum log level to output (default: warn)
* @param options.prefix - The prefix to add to the log message (default: "")
* @returns A logger instance with debug, info, warn, and error methods
*
* @example
* import { createLogger } from "@/utils/logging/logger";
*
* const logger = createLogger({ level: 'info' });
*
* logger.info('User logged in', { userId: '123' });
* logger.error('Operation failed', new Error('Connection timeout'));
*/
function createLogger(options = {}) {
const { level = "warn", prefix = "" } = options;
const logLevels = {
debug: 0,
info: 1,
warn: 2,
error: 3,
none: 4
};
const currentLevelValue = logLevels[level];
const formatArgs = (args) => {
if (args.length === 0 || args.every((arg) => arg === undefined || arg === null)) {
return "";
}
const formatted = args.map((arg) => {
if (arg instanceof Error) {
return `\n${arg.stack || arg.message}`;
}
if (typeof arg === "object" && arg !== null) {
return `\n${JSON.stringify(arg, null, 2)}`;
}
return ` ${String(arg)}`;
}).join("");
return `, args:${formatted}`;
};
const shouldLog = (level$1) => {
return logLevels[level$1] >= currentLevelValue;
};
return {
debug: (message, ...args) => {
if (shouldLog("debug")) {
console.debug(`\x1b[32m${prefix}[DEBUG] ${maskTokens(message)}${maskTokens(formatArgs(args))}\x1b[0m`);
}
},
info: (message, ...args) => {
if (shouldLog("info")) {
console.info(`\x1b[34m${prefix}[INFO] ${maskTokens(message)}${maskTokens(formatArgs(args))}\x1b[0m`);
}
},
warn: (message, ...args) => {
if (shouldLog("warn")) {
console.warn(`\x1b[33m${prefix}[WARN] ${maskTokens(message)}${maskTokens(formatArgs(args))}\x1b[0m`);
}
},
error: (message, ...args) => {
if (shouldLog("error")) {
console.error(`\x1b[31m${prefix}[ERROR] ${maskTokens(message)}${maskTokens(formatArgs(args))}\x1b[0m`);
}
}
};
}
/**
* Default logger instance with standard configuration
*/
const logger = createLogger();
//#endregion
//#region src/string.ts
/**
* Capitalizes the first letter of a string.
*
* @param val - The string to capitalize
* @returns The input string with its first letter capitalized
*
* @example
* import { capitalizeFirstLetter } from "@settlemint/sdk-utils";
*
* const capitalized = capitalizeFirstLetter("hello");
* // Returns: "Hello"
*/
function capitalizeFirstLetter(val) {
return String(val).charAt(0).toUpperCase() + String(val).slice(1);
}
/**
* Converts a camelCase string to a human-readable string.
*
* @param s - The camelCase string to convert
* @returns The human-readable string
*
* @example
* import { camelCaseToWords } from "@settlemint/sdk-utils";
*
* const words = camelCaseToWords("camelCaseString");
* // Returns: "Camel Case String"
*/
function camelCaseToWords(s) {
const result = s.replace(/([a-z])([A-Z])/g, "$1 $2");
const withSpaces = result.replace(/([A-Z])([a-z])/g, " $1$2");
const capitalized = capitalizeFirstLetter(withSpaces);
return capitalized.replace(/\s+/g, " ").trim();
}
/**
* Replaces underscores and hyphens with spaces.
*
* @param s - The string to replace underscores and hyphens with spaces
* @returns The input string with underscores and hyphens replaced with spaces
*
* @example
* import { replaceUnderscoresAndHyphensWithSpaces } from "@settlemint/sdk-utils";
*
* const result = replaceUnderscoresAndHyphensWithSpaces("Already_Spaced-Second");
* // Returns: "Already Spaced Second"
*/
function replaceUnderscoresAndHyphensWithSpaces(s) {
return s.replace(/[-_]/g, " ");
}
/**
* Truncates a string to a maximum length and appends "..." if it is longer.
*
* @param value - The string to truncate
* @param maxLength - The maximum length of the string
* @returns The truncated string or the original string if it is shorter than the maximum length
*
* @example
* import { truncate } from "@settlemint/sdk-utils";
*
* const truncated = truncate("Hello, world!", 10);
* // Returns: "Hello, wor..."
*/
function truncate(value, maxLength) {
if (value.length <= maxLength) {
return value;
}
return `${value.slice(0, maxLength)}...`;
}
//#endregion
//#region src/logging/request-logger.ts
const WARNING_THRESHOLD = 500;
const TRUNCATE_LENGTH = 50;
/**
* Logs the request and duration of a fetch call (> 500ms is logged as warn, otherwise info)
* @param logger - The logger to use
* @param name - The name of the request
* @param fn - The fetch function to use
* @returns The fetch function
*/
function requestLogger(logger$1, name, fn) {
return async (...args) => {
const start = Date.now();
try {
return await fn(...args);
} finally {
const end = Date.now();
const duration = end - start;
const body = extractInfoFromBody(args[1]?.body ?? "{}");
const message = `${name} path: ${args[0]}, took ${formatDuration(duration)}`;
if (duration > WARNING_THRESHOLD) {
logger$1.warn(message, body);
} else {
logger$1.info(message, body);
}
}
};
}
function formatDuration(duration) {
return duration < 1e3 ? `${duration}ms` : `${(duration / 1e3).toFixed(3)}s`;
}
function extractInfoFromBody(body) {
try {
const parsedBody = typeof body === "string" ? JSON.parse(body) : body;
if (parsedBody === null || parsedBody === undefined || Object.keys(parsedBody).length === 0) {
return null;
}
const dataToKeep = {};
if ("query" in parsedBody) {
dataToKeep.query = truncate(parsedBody.query, TRUNCATE_LENGTH);
}
if ("variables" in parsedBody) {
dataToKeep.variables = truncate(JSON.stringify(parsedBody.variables), TRUNCATE_LENGTH);
}
if ("operationName" in parsedBody) {
dataToKeep.operationName = truncate(parsedBody.operationName, TRUNCATE_LENGTH);
}
if (Object.keys(dataToKeep).length > 0) {
return JSON.stringify(dataToKeep);
}
return truncate(JSON.stringify(parsedBody || "{}"), TRUNCATE_LENGTH);
} catch {
return "{}";
}
}
//#endregion
exports.createLogger = createLogger;
exports.maskTokens = maskTokens;
exports.requestLogger = requestLogger;
//# sourceMappingURL=logging.cjs.map